techprotrade's picture
Deploy ATOM FastAPI command center runtime (part 6)
383cb38 verified
Raw
History Blame Contribute Delete
20.5 kB
#!/usr/bin/env python3
"""
ATOM Platform - OAuth Setup and Configuration Script
Complete OAuth setup for production deployment
"""
import json
import os
from pathlib import Path
import sys
from typing import Dict, List, Optional, Tuple
import webbrowser
import requests
class OAuthSetup:
"""OAuth setup and configuration manager"""
def __init__(self):
self.base_dir = Path(__file__).parent
self.oauth_server_url = "http://localhost:5058"
self.backend_url = "http://localhost:8000"
# OAuth service configuration
self.services = {
"github": {
"name": "GitHub",
"setup_url": "https://github.com/settings/applications/new",
"callback_url": f"{self.oauth_server_url}/api/auth/github/callback",
"scopes": ["repo", "user:email", "read:org"],
"required": True,
"env_vars": ["GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET"],
"setup_instructions": """
1. Go to GitHub Settings → Developer settings → OAuth Apps
2. Click "New OAuth App"
3. Application name: "ATOM Platform"
4. Homepage URL: http://localhost:3000 (or your domain)
5. Authorization callback URL: {callback_url}
6. Click "Register application"
7. Copy Client ID and Client Secret
""".strip(),
},
"google": {
"name": "Google",
"setup_url": "https://console.developers.google.com/apis/credentials",
"callback_url": f"{self.oauth_server_url}/api/auth/google/callback",
"scopes": [
"email",
"profile",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/drive",
],
"required": True,
"env_vars": ["GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET"],
"setup_instructions": """
1. Go to Google Cloud Console
2. Create a new project or select existing
3. Enable APIs: Calendar, Gmail, Drive
4. Go to Credentials → Create Credentials → OAuth 2.0 Client IDs
5. Application type: Web application
6. Name: "ATOM Platform"
7. Authorized redirect URIs: {callback_url}
8. Click "Create"
9. Copy Client ID and Client Secret
""".strip(),
},
"slack": {
"name": "Slack",
"setup_url": "https://api.slack.com/apps",
"callback_url": f"{self.oauth_server_url}/api/auth/slack/callback",
"scopes": ["chat:write", "channels:read", "groups:read", "users:read"],
"required": True,
"env_vars": ["SLACK_CLIENT_ID", "SLACK_CLIENT_SECRET"],
"setup_instructions": """
1. Go to Slack API: Create New App
2. Choose "From scratch"
3. App name: "ATOM Platform", Workspace: your workspace
4. Go to OAuth & Permissions
5. Add Redirect URLs: {callback_url}
6. Add Bot Token Scopes: chat:write, channels:read, groups:read, users:read
7. Install app to workspace
8. Copy OAuth Credentials: Client ID and Client Secret
""".strip(),
},
"dropbox": {
"name": "Dropbox",
"setup_url": "https://www.dropbox.com/developers/apps",
"callback_url": f"{self.oauth_server_url}/api/auth/dropbox/callback",
"scopes": [
"files.metadata.read",
"files.content.read",
"files.content.write",
],
"required": False,
"env_vars": ["DROPBOX_CLIENT_ID", "DROPBOX_CLIENT_SECRET"],
"setup_instructions": """
1. Go to Dropbox Developer Console
2. Create app → Scoped access
3. Choose access: App folder or Full Dropbox
4. App name: "ATOM Platform"
5. Go to Permissions tab, enable: files.metadata.read, files.content.read, files.content.write
6. Go to Settings tab
7. OAuth 2 → Redirect URIs: {callback_url}
8. Copy App key (Client ID) and App secret (Client Secret)
""".strip(),
},
"trello": {
"name": "Trello",
"setup_url": "https://trello.com/power-ups/admin",
"callback_url": f"{self.oauth_server_url}/api/auth/trello/callback",
"scopes": ["read", "write"],
"required": False,
"env_vars": ["TRELLO_CLIENT_ID", "TRELLO_CLIENT_SECRET"],
"setup_instructions": """
1. Go to Trello Developer API Keys
2. Click "Generate a new API key"
3. Application name: "ATOM Platform"
4. Description: "Workflow automation platform"
5. Accept terms and generate
6. Copy API Key (Client ID)
7. To get Secret: Click "Token" next to your API key
8. Generate a new token with read, write permissions
9. Copy Token (Client Secret)
""".strip(),
},
}
def check_current_status(self) -> Dict:
"""Check current OAuth configuration status"""
print("🔍 Checking current OAuth status...")
status = {}
try:
response = requests.get(
f"{self.oauth_server_url}/api/auth/services", timeout=10
)
if response.status_code == 200:
data = response.json()
status["total_services"] = data.get("total_services", 0)
status["configured_services"] = data.get(
"services_with_real_credentials", 0
)
status["needs_credentials"] = data.get(
"services_needing_credentials", 0
)
# Check individual service status
for service in self.services.keys():
try:
service_response = requests.get(
f"{self.oauth_server_url}/api/auth/{service}/status",
timeout=5,
)
if service_response.status_code == 200:
service_data = service_response.json()
status[service] = {
"configured": service_data.get("status")
== "configured",
"client_id": service_data.get("client_id", ""),
"message": service_data.get("message", ""),
}
except:
status[service] = {
"configured": False,
"error": "Service not reachable",
}
else:
print(" ❌ OAuth server not responding")
except Exception as e:
print(f" ❌ Error checking OAuth status: {e}")
return status
def print_status_report(self):
"""Print comprehensive OAuth status report"""
print("\n" + "=" * 60)
print("📊 ATOM PLATFORM - OAUTH CONFIGURATION STATUS")
print("=" * 60)
status = self.check_current_status()
if not status:
print("❌ Could not retrieve OAuth status")
return
print(f"\n📋 OVERVIEW:")
print(f" Total Services: {status.get('total_services', 0)}")
print(f" Configured: {status.get('configured_services', 0)}")
print(f" Needs Credentials: {status.get('needs_credentials', 0)}")
print(f"\n🔧 SERVICE STATUS:")
for service_name, service_config in self.services.items():
service_status = status.get(service_name, {})
if service_status.get("configured"):
print(f" ✅ {service_config['name']:12} - Configured")
else:
requirement = "REQUIRED" if service_config["required"] else "Optional"
print(
f" ❌ {service_config['name']:12} - Not configured ({requirement})"
)
def setup_service(self, service_name: str) -> bool:
"""Setup a specific OAuth service"""
if service_name not in self.services:
print(f"❌ Unknown service: {service_name}")
return False
service_config = self.services[service_name]
print(f"\n🔐 Setting up {service_config['name']} OAuth...")
print("=" * 50)
# Show setup instructions
instructions = service_config["setup_instructions"].format(
callback_url=service_config["callback_url"]
)
print(f"\n📚 SETUP INSTRUCTIONS:\n{instructions}")
# Open setup URL in browser
print(f"\n🌐 Opening setup page in browser...")
try:
webbrowser.open(service_config["setup_url"])
except:
print(
f" ⚠️ Could not open browser. Please visit: {service_config['setup_url']}"
)
# Get credentials from user
print(f"\n🔑 Please enter your {service_config['name']} credentials:")
client_id = input(f" Client ID: ").strip()
client_secret = input(f" Client Secret: ").strip()
if not client_id or not client_secret:
print(" ❌ Credentials cannot be empty")
return False
# Update environment
env_updated = self._update_environment(service_name, client_id, client_secret)
if env_updated:
print(f" ✅ {service_config['name']} credentials saved")
print(f" 🔄 Please restart the OAuth server to apply changes")
return True
else:
print(f" ❌ Failed to save credentials")
return False
def _update_environment(
self, service_name: str, client_id: str, client_secret: str
) -> bool:
"""Update environment variables with OAuth credentials"""
env_vars = self.services[service_name]["env_vars"]
# Try to update .env file
env_files = [".env", "real_credentials.env", ".env.production"]
for env_file in env_files:
file_path = self.base_dir / env_file
if file_path.exists():
return self._update_env_file(
file_path, env_vars[0], client_id, env_vars[1], client_secret
)
# Create new .env file if none exists
default_env = self.base_dir / ".env"
return self._update_env_file(
default_env, env_vars[0], client_id, env_vars[1], client_secret
)
def _update_env_file(
self,
file_path: Path,
client_id_var: str,
client_id: str,
client_secret_var: str,
client_secret: str,
) -> bool:
"""Update or create environment file"""
try:
if file_path.exists():
# Read existing content
content = file_path.read_text()
lines = content.split("\n")
# Update existing variables or add new ones
updated_lines = []
client_id_found = False
client_secret_found = False
for line in lines:
if line.startswith(f"{client_id_var}="):
updated_lines.append(f"{client_id_var}={client_id}")
client_id_found = True
elif line.startswith(f"{client_secret_var}="):
updated_lines.append(f"{client_secret_var}={client_secret}")
client_secret_found = True
else:
updated_lines.append(line)
# Add missing variables
if not client_id_found:
updated_lines.append(f"{client_id_var}={client_id}")
if not client_secret_found:
updated_lines.append(f"{client_secret_var}={client_secret}")
content = "\n".join(updated_lines)
else:
# Create new file
content = f"""# ATOM Platform - OAuth Configuration
{client_id_var}={client_id}
{client_secret_var}={client_secret}
"""
file_path.write_text(content)
print(f" ✅ Updated: {file_path.name}")
return True
except Exception as e:
print(f" ❌ Error updating {file_path}: {e}")
return False
def test_oauth_flow(self, service_name: str) -> bool:
"""Test OAuth flow for a service"""
if service_name not in self.services:
print(f"❌ Unknown service: {service_name}")
return False
print(f"\n🧪 Testing {self.services[service_name]['name']} OAuth flow...")
try:
# Check service status
response = requests.get(
f"{self.oauth_server_url}/api/auth/{service_name}/status", timeout=10
)
if response.status_code != 200:
print(f" ❌ Service status check failed: {response.status_code}")
return False
service_data = response.json()
if service_data.get("status") != "configured":
print(f" ❌ Service not configured: {service_data.get('message')}")
return False
# Try to generate authorization URL
auth_response = requests.get(
f"{self.oauth_server_url}/api/auth/{service_name}/authorize",
params={"user_id": "test_user"},
timeout=10,
)
if auth_response.status_code == 200:
auth_data = auth_response.json()
if auth_data.get("credentials") == "real":
print(f" ✅ OAuth flow working - Authorization URL generated")
print(f" 🔗 Auth URL: {auth_data.get('auth_url')}")
return True
else:
print(f" ❌ Using placeholder credentials")
return False
else:
print(f" ❌ Authorization failed: {auth_response.status_code}")
return False
except Exception as e:
print(f" ❌ OAuth test failed: {e}")
return False
def setup_all_required(self) -> bool:
"""Setup all required OAuth services"""
print("\n🚀 Setting up all required OAuth services...")
required_services = [
name for name, config in self.services.items() if config["required"]
]
success_count = 0
for service_name in required_services:
if self.setup_service(service_name):
success_count += 1
else:
print(f" ⚠️ Failed to setup {service_name}")
print(
f"\n📊 Setup completed: {success_count}/{len(required_services)} required services configured"
)
return success_count == len(required_services)
def generate_setup_guide(self):
"""Generate comprehensive setup guide"""
guide_file = self.base_dir / "OAUTH_SETUP_GUIDE.md"
guide_content = f"""# ATOM Platform - OAuth Setup Guide
## Overview
This guide will help you configure OAuth integrations for the ATOM Platform.
## Prerequisites
- Running ATOM Platform services
- Admin access to the services you want to integrate
## Service Configuration
"""
for service_name, service_config in self.services.items():
requirement = "**REQUIRED**" if service_config["required"] else "Optional"
instructions = service_config["setup_instructions"].format(
callback_url=service_config["callback_url"]
)
guide_content += f"""### {service_config["name"]} ({requirement})
{instructions}
**Environment Variables:**
- `{service_config["env_vars"][0]}` = Your Client ID
- `{service_config["env_vars"][1]}` = Your Client Secret
**Callback URL:** `{service_config["callback_url"]}`
---
"""
guide_content += """
## Verification Steps
1. **Check Current Status:**
```bash
python setup_oauth.py --status
```
2. **Setup Individual Service:**
```bash
python setup_oauth.py --setup github
```
3. **Setup All Required Services:**
```bash
python setup_oauth.py --setup-all
```
4. **Test OAuth Flow:**
```bash
python setup_oauth.py --test github
```
## Troubleshooting
### Common Issues
1. **"Service not configured"**
- Check that environment variables are set
- Restart OAuth server after setting variables
2. **"Invalid redirect URI"**
- Ensure callback URL matches exactly
- Include http:// or https:// prefix
3. **"Invalid client credentials"**
- Verify Client ID and Client Secret
- Check for typos or extra spaces
### Support
For additional help, check the ATOM Platform documentation or contact support.
"""
guide_file.write_text(guide_content)
print(f"✅ Setup guide generated: {guide_file.name}")
def run_interactive_setup(self):
"""Run interactive OAuth setup"""
print("🚀 ATOM Platform - Interactive OAuth Setup")
print("=" * 50)
while True:
print("\n📋 OPTIONS:")
print("1. Check OAuth status")
print("2. Setup specific service")
print("3. Setup all required services")
print("4. Test OAuth flow")
print("5. Generate setup guide")
print("6. Exit")
choice = input("\nEnter your choice (1-6): ").strip()
if choice == "1":
self.print_status_report()
elif choice == "2":
print("\nAvailable services:")
for i, (name, config) in enumerate(self.services.items(), 1):
requirement = "REQUIRED" if config["required"] else "Optional"
print(f" {i}. {config['name']} ({requirement})")
service_choice = input("\nEnter service number or name: ").strip()
if service_choice.isdigit():
service_index = int(service_choice) - 1
service_names = list(self.services.keys())
if 0 <= service_index < len(service_names):
self.setup_service(service_names[service_index])
else:
print("❌ Invalid service number")
else:
self.setup_service(service_choice.lower())
elif choice == "3":
self.setup_all_required()
elif choice == "4":
service_name = input("Enter service name to test: ").strip().lower()
self.test_oauth_flow(service_name)
elif choice == "5":
self.generate_setup_guide()
elif choice == "6":
print("👋 Goodbye!")
break
else:
print("❌ Invalid choice. Please enter 1-6.")
def run_cli_setup(self, args):
"""Run CLI-based setup"""
if "--status" in args:
self.print_status_report()
elif "--setup" in args:
if len(args) > 2:
self.setup_service(args[2])
else:
print("❌ Please specify service: --setup [service_name]")
elif "--setup-all" in args:
self.setup_all_required()
elif "--test" in args:
if len(args) > 2:
self.test_oauth_flow(args[2])
else:
print("❌ Please specify service: --test [service_name]")
elif "--guide" in args:
self.generate_setup_guide()
else:
print("Usage: python setup_oauth.py [OPTION]")
print("Options:")
print(" --status Check OAuth configuration status")
print(" --setup SERVICE Setup specific OAuth service")
print(" --setup-all Setup all required OAuth services")
print(" --test SERVICE Test OAuth flow for service")
print(" --guide Generate setup guide")
print(" --interactive Run interactive setup")
def main():
"""Main function"""
setup = OAuthSetup()
if len(sys.argv) > 1:
setup.run_cli_setup(sys.argv)
else:
setup.run_interactive_setup()
if __name__ == "__main__":
main()