Spaces:
Paused
Paused
| from typing import Optional, Dict, Any | |
| from datetime import datetime, timedelta | |
| import secrets | |
| import json | |
| from pathlib import Path | |
| class AuthManager: | |
| """Manages authentication for HuggingFace Spaces OAuth""" | |
| def __init__(self): | |
| # OAuth scopes for HuggingFace Spaces | |
| self.oauth_scopes = [ | |
| "read-repos", | |
| "write-repos" | |
| ] | |
| # Session management | |
| self.sessions = {} | |
| self.session_timeout = timedelta(hours=8) | |
| def get_oauth_config(self) -> Dict[str, Any]: | |
| """Get OAuth configuration for HuggingFace Spaces""" | |
| return { | |
| "provider": "huggingface", | |
| "scopes": self.oauth_scopes, | |
| "expiration_minutes": 480, # 8 hours | |
| "allow_anonymous": False | |
| } | |
| def validate_session(self, session_token: str) -> Optional[Dict[str, Any]]: | |
| """Validate a session token""" | |
| if session_token in self.sessions: | |
| session = self.sessions[session_token] | |
| if datetime.now() < session['expires']: | |
| # Update last access | |
| session['last_access'] = datetime.now() | |
| return session['user_data'] | |
| return None | |
| def create_session(self, oauth_profile: Dict[str, Any]) -> str: | |
| """Create a new session for authenticated user""" | |
| session_token = secrets.token_urlsafe(32) | |
| self.sessions[session_token] = { | |
| 'user_data': { | |
| 'username': oauth_profile.get('preferred_username', oauth_profile.get('username')), | |
| 'name': oauth_profile.get('name', 'Anonymous'), | |
| 'avatar_url': oauth_profile.get('picture', oauth_profile.get('avatar_url')), | |
| 'auth_time': datetime.now().isoformat() | |
| }, | |
| 'created': datetime.now(), | |
| 'expires': datetime.now() + self.session_timeout, | |
| 'last_access': datetime.now() | |
| } | |
| return session_token | |
| def cleanup_expired_sessions(self): | |
| """Remove expired sessions""" | |
| current_time = datetime.now() | |
| expired_tokens = [ | |
| token for token, session in self.sessions.items() | |
| if current_time > session['expires'] | |
| ] | |
| for token in expired_tokens: | |
| del self.sessions[token] | |
| def get_user_permissions(self, username: str) -> Dict[str, bool]: | |
| """Get user permissions""" | |
| # In HuggingFace Spaces, all authenticated users have same permissions | |
| return { | |
| 'can_create_monster': True, | |
| 'can_train': True, | |
| 'can_evolve': True, | |
| 'can_battle': True, | |
| 'can_export': True, | |
| 'max_monsters': 10, | |
| 'max_daily_generations': 50 | |
| } | |
| def log_user_action(self, username: str, action: str, details: Dict = None): | |
| """Log user actions for analytics""" | |
| # This would typically write to a database or analytics service | |
| # For HF Spaces, we'll just print for now | |
| log_entry = { | |
| 'timestamp': datetime.now().isoformat(), | |
| 'username': username, | |
| 'action': action, | |
| 'details': details or {} | |
| } | |
| print(f"User Action: {json.dumps(log_entry)}") | |
| def format_oauth_button_config(self) -> Dict[str, Any]: | |
| """Format configuration for Gradio LoginButton""" | |
| return { | |
| "value": "Connect to Digital World", | |
| "size": "lg", | |
| "icon": "π", | |
| "variant": "primary" | |
| } |