Spaces:
Sleeping
Sleeping
| [1mdiff --git a/EMAIL_SETUP_GUIDE.md b/EMAIL_SETUP_GUIDE.md[m | |
| [1mdeleted file mode 100644[m | |
| [1mindex f22eac2..0000000[m | |
| [1m--- a/EMAIL_SETUP_GUIDE.md[m | |
| [1m+++ /dev/null[m | |
| [36m@@ -1,137 +0,0 @@[m | |
| [31m-# π§ Gmail Email Setup Guide[m | |
| [31m-[m | |
| [31m-This guide will help you set up Gmail SMTP for the password reset functionality.[m | |
| [31m-[m | |
| [31m-## π What You Need[m | |
| [31m-[m | |
| [31m-1. **Gmail Email Address** (your username)[m | |
| [31m-2. **Gmail App Password** (16-character password)[m | |
| [31m-[m | |
| [31m-## π Step-by-Step Setup[m | |
| [31m-[m | |
| [31m-### Step 1: Get Your Gmail Username[m | |
| [31m-- Your Gmail username is your Gmail email address[m | |
| [31m-- **Example**: `john.doe@gmail.com`[m | |
| [31m-[m | |
| [31m-### Step 2: Create Gmail App Password[m | |
| [31m-[m | |
| [31m-#### 2.1 Enable 2-Step Verification[m | |
| [31m-1. Go to: https://myaccount.google.com/security[m | |
| [31m-2. Sign in with your Gmail account[m | |
| [31m-3. Find "2-Step Verification" and click "Get started"[m | |
| [31m-4. Follow the setup process (usually involves your phone)[m | |
| [31m-[m | |
| [31m-#### 2.2 Generate App Password[m | |
| [31m-1. After enabling 2-Step Verification, go back to: https://myaccount.google.com/security[m | |
| [31m-2. Scroll down and find "App passwords"[m | |
| [31m-3. Click on "App passwords"[m | |
| [31m-4. Select "Mail" as the app[m | |
| [31m-5. Select "Other (Custom name)" as the device[m | |
| [31m-6. Enter a name like "CPS Password Reset"[m | |
| [31m-7. Click "Generate"[m | |
| [31m-8. **Copy the 16-character password** (remove spaces)[m | |
| [31m-[m | |
| [31m-**Example App Password**: `abcd efgh ijkl mnop` β `abcdefghijklmnop`[m | |
| [31m-[m | |
| [31m-### Step 3: Configure Environment Variables[m | |
| [31m-[m | |
| [31m-#### Option A: Create .env file (Recommended)[m | |
| [31m-Create a file named `.env` in the `cps-api-tx` directory:[m | |
| [31m-[m | |
| [31m-```bash[m | |
| [31m-# Database Configuration[m | |
| [31m-MONGODB_URL=mongodb://localhost:27017/cps_db[m | |
| [31m-[m | |
| [31m-# JWT Configuration[m | |
| [31m-SECRET_KEY=your-secret-key-here[m | |
| [31m-ALGORITHM=HS256[m | |
| [31m-ACCESS_TOKEN_EXPIRE_MINUTES=30[m | |
| [31m-[m | |
| [31m-# Email Configuration (REPLACE WITH YOUR ACTUAL VALUES)[m | |
| [31m-MAIL_USERNAME=your-email@gmail.com[m | |
| [31m-MAIL_PASSWORD=your-16-character-app-password[m | |
| [31m-MAIL_FROM=your-email@gmail.com[m | |
| [31m-[m | |
| [31m-# TxAgent Configuration[m | |
| [31m-TXAGENT_MODE=cloud[m | |
| [31m-TXAGENT_CLOUD_URL=https://rocketfarmstudios-txagent-api.hf.space[m | |
| [31m-TXAGENT_LOCAL_ENABLED=false[m | |
| [31m-[m | |
| [31m-# CORS Configuration[m | |
| [31m-ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8081[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-#### Option B: Set Environment Variables in Terminal[m | |
| [31m-[m | |
| [31m-**Windows (PowerShell)**:[m | |
| [31m-```powershell[m | |
| [31m-$env:MAIL_USERNAME="your-email@gmail.com"[m | |
| [31m-$env:MAIL_PASSWORD="your-16-character-app-password"[m | |
| [31m-$env:MAIL_FROM="your-email@gmail.com"[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-**Windows (Command Prompt)**:[m | |
| [31m-```cmd[m | |
| [31m-set MAIL_USERNAME=your-email@gmail.com[m | |
| [31m-set MAIL_PASSWORD=your-16-character-app-password[m | |
| [31m-set MAIL_FROM=your-email@gmail.com[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-**Linux/Mac**:[m | |
| [31m-```bash[m | |
| [31m-export MAIL_USERNAME="your-email@gmail.com"[m | |
| [31m-export MAIL_PASSWORD="your-16-character-app-password"[m | |
| [31m-export MAIL_FROM="your-email@gmail.com"[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-### Step 4: Test Your Configuration[m | |
| [31m-[m | |
| [31m-Run the test script to verify your setup:[m | |
| [31m-[m | |
| [31m-```bash[m | |
| [31m-cd cps-api-tx[m | |
| [31m-python test_email_config.py[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-## π Troubleshooting[m | |
| [31m-[m | |
| [31m-### Common Issues:[m | |
| [31m-[m | |
| [31m-1. **"Username and Password not accepted"**[m | |
| [31m- - Make sure you're using an App Password, not your regular Gmail password[m | |
| [31m- - Ensure 2-Step Verification is enabled[m | |
| [31m- - Check that the App Password is exactly 16 characters (no spaces)[m | |
| [31m-[m | |
| [31m-2. **"App passwords not available"**[m | |
| [31m- - 2-Step Verification must be enabled first[m | |
| [31m- - Wait a few minutes after enabling 2-Step Verification[m | |
| [31m-[m | |
| [31m-3. **"SMTP connection failed"**[m | |
| [31m- - Check your internet connection[m | |
| [31m- - Ensure Gmail SMTP is not blocked by firewall[m | |
| [31m- - Try using port 587 (should be automatic)[m | |
| [31m-[m | |
| [31m-### Security Notes:[m | |
| [31m-[m | |
| [31m-- β **App Passwords are secure** - they can only be used for the specific app[m | |
| [31m-- β **You can revoke App Passwords** anytime from Google Account settings[m | |
| [31m-- β **App Passwords don't expire** unless you change your main password[m | |
| [31m-- β **Never share your App Password** with anyone[m | |
| [31m-- β **Don't commit .env files** to version control[m | |
| [31m-[m | |
| [31m-## π Need Help?[m | |
| [31m-[m | |
| [31m-If you're still having issues:[m | |
| [31m-[m | |
| [31m-1. **Check Google Account Activity**: https://myaccount.google.com/notifications[m | |
| [31m-2. **Review App Passwords**: https://myaccount.google.com/apppasswords[m | |
| [31m-3. **Google Account Help**: https://support.google.com/accounts[m | |
| [31m-[m | |
| [31m-## β Verification Checklist[m | |
| [31m-[m | |
| [31m-- [ ] 2-Step Verification enabled[m | |
| [31m-- [ ] App Password generated for "Mail"[m | |
| [31m-- [ ] 16-character App Password copied (no spaces)[m | |
| [31m-- [ ] Environment variables set correctly[m | |
| [31m-- [ ] Test script runs successfully[m | |
| [31m-- [ ] Test email received in inbox[m | |
| [1mdiff --git a/ENHANCED_APPOINTMENT_GUIDE.md b/ENHANCED_APPOINTMENT_GUIDE.md[m | |
| [1mdeleted file mode 100644[m | |
| [1mindex 8b13789..0000000[m | |
| [1m--- a/ENHANCED_APPOINTMENT_GUIDE.md[m | |
| [1m+++ /dev/null[m | |
| [36m@@ -1 +0,0 @@[m | |
| [31m-[m | |
| [1mdiff --git a/PASSWORD_RESET_SETUP.md b/PASSWORD_RESET_SETUP.md[m | |
| [1mdeleted file mode 100644[m | |
| [1mindex 543b3ef..0000000[m | |
| [1m--- a/PASSWORD_RESET_SETUP.md[m | |
| [1m+++ /dev/null[m | |
| [36m@@ -1,122 +0,0 @@[m | |
| [31m-# Password Reset Setup Guide[m | |
| [31m-[m | |
| [31m-This guide explains how to set up the password reset functionality with email verification.[m | |
| [31m-[m | |
| [31m-## Email Configuration[m | |
| [31m-[m | |
| [31m-The password reset feature uses Gmail SMTP to send verification codes. You need to configure the following environment variables:[m | |
| [31m-[m | |
| [31m-### 1. Create a Gmail App Password[m | |
| [31m-[m | |
| [31m-1. Go to your Google Account settings[m | |
| [31m-2. Navigate to Security > 2-Step Verification[m | |
| [31m-3. Create an App Password for your application[m | |
| [31m-4. Use this app password instead of your regular Gmail password[m | |
| [31m-[m | |
| [31m-### 2. Environment Variables[m | |
| [31m-[m | |
| [31m-Add these variables to your `.env` file or environment:[m | |
| [31m-[m | |
| [31m-```bash[m | |
| [31m-# Email Configuration[m | |
| [31m-MAIL_USERNAME=your-email@gmail.com[m | |
| [31m-MAIL_PASSWORD=your-app-password-here[m | |
| [31m-MAIL_FROM=your-email@gmail.com[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-### 3. Install Dependencies[m | |
| [31m-[m | |
| [31m-Make sure you have the required packages installed:[m | |
| [31m-[m | |
| [31m-```bash[m | |
| [31m-pip install fastapi-mail jinja2[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-## API Endpoints[m | |
| [31m-[m | |
| [31m-The password reset functionality provides three endpoints:[m | |
| [31m-[m | |
| [31m-### 1. Request Password Reset[m | |
| [31m-```[m | |
| [31m-POST /auth/forgot-password[m | |
| [31m-Content-Type: application/json[m | |
| [31m-[m | |
| [31m-{[m | |
| [31m- "email": "user@example.com"[m | |
| [31m-}[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-### 2. Verify Reset Code[m | |
| [31m-```[m | |
| [31m-POST /auth/verify-reset-code[m | |
| [31m-Content-Type: application/json[m | |
| [31m-[m | |
| [31m-{[m | |
| [31m- "email": "user@example.com",[m | |
| [31m- "verification_code": "123456"[m | |
| [31m-}[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-### 3. Reset Password[m | |
| [31m-```[m | |
| [31m-POST /auth/reset-password[m | |
| [31m-Content-Type: application/json[m | |
| [31m-[m | |
| [31m-{[m | |
| [31m- "email": "user@example.com",[m | |
| [31m- "verification_code": "123456",[m | |
| [31m- "new_password": "newpassword123"[m | |
| [31m-}[m | |
| [31m-```[m | |
| [31m-[m | |
| [31m-## Security Features[m | |
| [31m-[m | |
| [31m-- **6-digit verification codes** with 15-minute expiration[m | |
| [31m-- **One-time use codes** - each code can only be used once[m | |
| [31m-- **Email validation** - checks if the email exists before sending[m | |
| [31m-- **Password validation** - minimum 6 characters required[m | |
| [31m-- **Secure email templates** with professional styling[m | |
| [31m-[m | |
| [31m-## Frontend Integration[m | |
| [31m-[m | |
| [31m-### Web App (React)[m | |
| [31m-The web app includes a complete password reset flow with:[m | |
| [31m-- 3-step wizard interface[m | |
| [31m-- Real-time validation[m | |
| [31m-- Progress indicators[m | |
| [31m-- Error handling[m | |
| [31m-[m | |
| [31m-### Mobile App (React Native)[m | |
| [31m-The mobile app includes:[m | |
| [31m-- Native password reset screen[m | |
| [31m-- Progress bar and step indicators[m | |
| [31m-- Snackbar notifications[m | |
| [31m-- Keyboard-aware interface[m | |
| [31m-[m | |
| [31m-## Testing[m | |
| [31m-[m | |
| [31m-1. Start the backend server[m | |
| [31m-2. Configure email settings[m | |
| [31m-3. Test the password reset flow:[m | |
| [31m- - Request reset for existing email[m | |
| [31m- - Check email for verification code[m | |
| [31m- - Verify code[m | |
| [31m- - Set new password[m | |
| [31m- - Sign in with new password[m | |
| [31m-[m | |
| [31m-## Troubleshooting[m | |
| [31m-[m | |
| [31m-### Email Not Sending[m | |
| [31m-- Check Gmail app password configuration[m | |
| [31m-- Verify SMTP settings[m | |
| [31m-- Check firewall/network restrictions[m | |
| [31m-[m | |
| [31m-### Verification Code Issues[m | |
| [31m-- Codes expire after 15 minutes[m | |
| [31m-- Each code can only be used once[m | |
| [31m-- Check database connection for code storage[m | |
| [31m-[m | |
| [31m-### Frontend Issues[m | |
| [31m-- Verify API endpoint URLs[m | |
| [31m-- Check CORS configuration[m | |
| [31m-- Ensure proper error handling[m | |
| [1mdiff --git a/api/routes/auth.py b/api/routes/auth.py[m | |
| [1mindex 334e365..a44b00e 100644[m | |
| [1m--- a/api/routes/auth.py[m | |
| [1m+++ b/api/routes/auth.py[m | |
| [36m@@ -107,7 +107,7 @@[m [masync def create_doctor([m | |
| "license_number": data.license_number,[m | |
| "created_at": datetime.utcnow().isoformat(),[m | |
| "updated_at": datetime.utcnow().isoformat(),[m | |
| [31m- "device_token": data.device_token or ""[m | |
| [32m+[m[32m "device_token": "" # Default empty device token for doctors[m | |
| }[m | |
| [m | |
| try:[m | |
| [1mdiff --git a/check_database.py b/check_database.py[m | |
| [1mdeleted file mode 100644[m | |
| [1mindex e88aad6..0000000[m | |
| [1m--- a/check_database.py[m | |
| [1m+++ /dev/null[m | |
| [36m@@ -1,98 +0,0 @@[m | |
| [31m-#!/usr/bin/env python3[m | |
| [31m-"""[m | |
| [31m-Check database directly to see analysis data[m | |
| [31m-"""[m | |
| [31m-[m | |
| [31m-import asyncio[m | |
| [31m-import motor.motor_asyncio[m | |
| [31m-import os[m | |
| [31m-from datetime import datetime[m | |
| [31m-[m | |
| [31m-async def check_database():[m | |
| [31m- """Check database directly for analysis data"""[m | |
| [31m- [m | |
| [31m- print("π Checking Database Directly")[m | |
| [31m- print("=" * 50)[m | |
| [31m- print(f"β° Started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")[m | |
| [31m- print()[m | |
| [31m- [m | |
| [31m- try:[m | |
| [31m- # Connect to MongoDB[m | |
| [31m- mongo_url = os.getenv('MONGODB_URL', 'mongodb://localhost:27017')[m | |
| [31m- client = motor.motor_asyncio.AsyncIOMotorClient(mongo_url)[m | |
| [31m- db = client.cps_database[m | |
| [31m- [m | |
| [31m- # Check patients collection[m | |
| [31m- print("π Checking patients collection...")[m | |
| [31m- patients_count = await db.patients.count_documents({})[m | |
| [31m- print(f" β Found {patients_count} patients")[m | |
| [31m- [m | |
| [31m- if patients_count > 0:[m | |
| [31m- # Show sample patients[m | |
| [31m- patients = await db.patients.find({}).limit(3).to_list(length=3)[m | |
| [31m- print("\nπ Sample Patients:")[m | |
| [31m- for i, patient in enumerate(patients):[m | |
| [31m- print(f" Patient {i+1}: {patient.get('full_name', 'Unknown')}")[m | |
| [31m- print(f" - ID: {patient.get('fhir_id', 'No ID')}")[m | |
| [31m- print(f" - Email: {patient.get('email', 'No email')}")[m | |
| [31m- print()[m | |
| [31m- [m | |
| [31m- # Check analysis collection[m | |
| [31m- print("π Checking analysis collection...")[m | |
| [31m- analysis_count = await db.patient_analysis_results.count_documents({})[m | |
| [31m- print(f" β Found {analysis_count} analysis results")[m | |
| [31m- [m | |
| [31m- if analysis_count > 0:[m | |
| [31m- # Show sample analysis results[m | |
| [31m- analyses = await db.patient_analysis_results.find({}).limit(3).to_list(length=3)[m | |
| [31m- print("\nπ Sample Analysis Results:")[m | |
| [31m- for i, analysis in enumerate(analyses):[m | |
| [31m- print(f" Analysis {i+1}:")[m | |
| [31m- print(f" - Patient ID: {analysis.get('patient_id', 'No ID')}")[m | |
| [31m- print(f" - Timestamp: {analysis.get('timestamp', 'No timestamp')}")[m | |
| [31m- [m | |
| [31m- # Check suicide risk data[m | |
| [31m- suicide_risk = analysis.get('suicide_risk', {})[m | |
| [31m- if isinstance(suicide_risk, dict):[m | |
| [31m- risk_level = suicide_risk.get('level', 'No level')[m | |
| [31m- risk_score = suicide_risk.get('score', 0.0)[m | |
| [31m- risk_factors = suicide_risk.get('factors', [])[m | |
| [31m- print(f" - Risk Level: {risk_level}")[m | |
| [31m- print(f" - Risk Score: {risk_score}")[m | |
| [31m- print(f" - Risk Factors: {risk_factors}")[m | |
| [31m- else:[m | |
| [31m- print(f" - Suicide Risk: {suicide_risk}")[m | |
| [31m- [m | |
| [31m- # Check summary[m | |
| [31m- summary = analysis.get('summary', '')[m | |
| [31m- if summary:[m | |
| [31m- print(f" - Summary: {summary[:100]}...")[m | |
| [31m- print()[m | |
| [31m- [m | |
| [31m- # Check if there are any patients without analysis[m | |
| [31m- if patients_count > 0 and analysis_count > 0:[m | |
| [31m- print("π Checking for patients without analysis...")[m | |
| [31m- patients_with_analysis = await db.patient_analysis_results.distinct('patient_id')[m | |
| [31m- patients_without_analysis = patients_count - len(patients_with_analysis)[m | |
| [31m- print(f" π Patients with analysis: {len(patients_with_analysis)}")[m | |
| [31m- print(f" π Patients without analysis: {patients_without_analysis}")[m | |
| [31m- [m | |
| [31m- if patients_without_analysis > 0:[m | |
| [31m- print(" β οΈ Some patients need analysis!")[m | |
| [31m- print(" π‘ You may need to trigger analysis for these patients")[m | |
| [31m- [m | |
| [31m- client.close()[m | |
| [31m- [m | |
| [31m- except Exception as e:[m | |
| [31m- print(f"β Database error: {e}")[m | |
| [31m- print("π‘ Make sure MongoDB is running and accessible")[m | |
| [31m- [m | |
| [31m- print("\n" + "="*50)[m | |
| [31m- print("β Database check completed!")[m | |
| [31m- print("\nπ Summary:")[m | |
| [31m- print(" - If you see analysis results with real scores, the data exists")[m | |
| [31m- print(" - If scores are 0.0, the analysis may need to be re-run")[m | |
| [31m- print(" - Your mobile app should show real scores if data exists")[m | |
| [31m-[m | |
| [31m-if __name__ == "__main__":[m | |
| [31m- asyncio.run(check_database())[m | |
| [1mdiff --git a/monitor_and_trigger.py b/monitor_and_trigger.py[m | |
| [1mdeleted file mode 100644[m | |
| [1mindex 82df60b..0000000[m | |
| [1m--- a/monitor_and_trigger.py[m | |
| [1m+++ /dev/null[m | |
| [36m@@ -1,124 +0,0 @@[m | |
| [31m-#!/usr/bin/env python3[m | |
| [31m-"""[m | |
| [31m-Monitor Hugging Face Space and automatically trigger analysis when it comes online[m | |
| [31m-"""[m | |
| [31m-[m | |
| [31m-import asyncio[m | |
| [31m-import aiohttp[m | |
| [31m-import json[m | |
| [31m-import time[m | |
| [31m-from datetime import datetime[m | |
| [31m-[m | |
| [31m-async def monitor_and_trigger():[m | |
| [31m- """Monitor the space and trigger analysis when it comes online"""[m | |
| [31m- [m | |
| [31m- space_url = "https://rocketfarmstudios-cps-api-tx.hf.space"[m | |
| [31m- [m | |
| [31m- print("π Monitoring cps-api-tx Hugging Face Space")[m | |
| [31m- print("=" * 60)[m | |
| [31m- print(f"π‘ Space URL: {space_url}")[m | |
| [31m- print(f"β° Started monitoring at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")[m | |
| [31m- print()[m | |
| [31m- print("π‘ Please restart your Hugging Face Space while this is running!")[m | |
| [31m- print(" Go to: https://huggingface.co/spaces/RocketFarmStudios/cps-api-tx")[m | |
| [31m- print()[m | |
| [31m- [m | |
| [31m- attempt = 1[m | |
| [31m- while True:[m | |
| [31m- try:[m | |
| [31m- async with aiohttp.ClientSession() as session:[m | |
| [31m- async with session.get(space_url, timeout=10) as response:[m | |
| [31m- if response.status == 200:[m | |
| [31m- print(f"β SUCCESS! Space is now ONLINE! (Attempt {attempt})")[m | |
| [31m- print(f"β° Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")[m | |
| [31m- print()[m | |
| [31m- [m | |
| [31m- # Test the root endpoint[m | |
| [31m- root_data = await response.text()[m | |
| [31m- print(f"π Root endpoint response: {root_data}")[m | |
| [31m- print()[m | |
| [31m- [m | |
| [31m- # Wait a moment for the space to fully initialize[m | |
| [31m- print("β³ Waiting 30 seconds for space to fully initialize...")[m | |
| [31m- await asyncio.sleep(30)[m | |
| [31m- [m | |
| [31m- # Trigger analysis[m | |
| [31m- print("π Triggering analysis for all patients...")[m | |
| [31m- try:[m | |
| [31m- analyze_url = f"{space_url}/txagent/patients/analyze"[m | |
| [31m- async with session.post(analyze_url, timeout=120) as analyze_response: # 2 minute timeout[m | |
| [31m- if analyze_response.status == 200:[m | |
| [31m- result_data = await analyze_response.json()[m | |
| [31m- print("β Analysis triggered successfully!")[m | |
| [31m- print(f"π Results: {json.dumps(result_data, indent=2)}")[m | |
| [31m- [m | |
| [31m- analyzed_count = result_data.get('analyzed_count', 0)[m | |
| [31m- total_patients = result_data.get('total_patients', 0)[m | |
| [31m- [m | |
| [31m- if analyzed_count > 0:[m | |
| [31m- print(f"π Successfully analyzed {analyzed_count}/{total_patients} patients!")[m | |
| [31m- [m | |
| [31m- # Check results[m | |
| [31m- print("\nπ Checking analysis results...")[m | |
| [31m- results_url = f"{space_url}/txagent/patients/analysis-results"[m | |
| [31m- async with session.get(results_url, timeout=10) as results_response:[m | |
| [31m- if results_response.status == 200:[m | |
| [31m- results_data = await results_response.json()[m | |
| [31m- print(f"β Found {len(results_data)} analysis results")[m | |
| [31m- [m | |
| [31m- if len(results_data) > 0:[m | |
| [31m- print("\nπ Sample Results with Real Scores:")[m | |
| [31m- for i, result in enumerate(results_data[:3]):[m | |
| [31m- suicide_risk = result.get('suicide_risk', {})[m | |
| [31m- |