OpenHands/enterprise/server/auth/github_utils.py
2025-09-04 15:44:54 -04:00

127 lines
4.4 KiB
Python

import os
from integrations.github.github_service import SaaSGitHubService
from pydantic import SecretStr
from server.auth.sheets_client import GoogleSheetsClient
from openhands.core.logger import openhands_logger as logger
from openhands.integrations.github.github_types import GitHubUser
class UserVerifier:
def __init__(self) -> None:
logger.debug('Initializing UserVerifier')
self.file_users: list[str] | None = None
self.sheets_client: GoogleSheetsClient | None = None
self.spreadsheet_id: str | None = None
# Initialize from environment variables
self._init_file_users()
self._init_sheets_client()
def _init_file_users(self) -> None:
"""Load users from text file if configured"""
waitlist = os.getenv('GITHUB_USER_LIST_FILE')
if not waitlist:
logger.debug('GITHUB_USER_LIST_FILE not configured')
return
if not os.path.exists(waitlist):
logger.error(f'User list file not found: {waitlist}')
raise FileNotFoundError(f'User list file not found: {waitlist}')
try:
with open(waitlist, 'r') as f:
self.file_users = [line.strip().lower() for line in f if line.strip()]
logger.info(
f'Successfully loaded {len(self.file_users)} users from {waitlist}'
)
except Exception:
logger.error(f'Error reading user list file {waitlist}', exc_info=True)
def _init_sheets_client(self) -> None:
"""Initialize Google Sheets client if configured"""
sheet_id = os.getenv('GITHUB_USERS_SHEET_ID')
if not sheet_id:
logger.debug('GITHUB_USERS_SHEET_ID not configured')
return
logger.debug('Initializing Google Sheets integration')
self.sheets_client = GoogleSheetsClient()
self.spreadsheet_id = sheet_id
def is_active(self) -> bool:
if os.getenv('DISABLE_WAITLIST', '').lower() == 'true':
logger.info('Waitlist disabled via DISABLE_WAITLIST env var')
return False
return bool(self.file_users or (self.sheets_client and self.spreadsheet_id))
def is_user_allowed(self, username: str) -> bool:
"""Check if user is allowed based on file and/or sheet configuration"""
logger.debug(f'Checking if GitHub user {username} is allowed')
if self.file_users:
if username.lower() in self.file_users:
logger.debug(f'User {username} found in text file allowlist')
return True
logger.debug(f'User {username} not found in text file allowlist')
if self.sheets_client and self.spreadsheet_id:
sheet_users = [
u.lower() for u in self.sheets_client.get_usernames(self.spreadsheet_id)
]
if username.lower() in sheet_users:
logger.debug(f'User {username} found in Google Sheets allowlist')
return True
logger.debug(f'User {username} not found in Google Sheets allowlist')
logger.debug(f'User {username} not found in any allowlist')
return False
user_verifier = UserVerifier()
def is_user_allowed(user_login: str):
if user_verifier.is_active() and not user_verifier.is_user_allowed(user_login):
logger.warning(f'GitHub user {user_login} not in allow list')
return False
return True
async def authenticate_github_user_id(auth_user_id: str) -> GitHubUser | None:
logger.debug('Checking auth status for GitHub user')
if not auth_user_id:
logger.warning('No GitHub User ID provided')
return None
gh_service = SaaSGitHubService(user_id=auth_user_id)
try:
user: GitHubUser = await gh_service.get_user()
if is_user_allowed(user.login):
return user
return None
except: # noqa: E722
logger.warning("GitHub user doens't have valid token")
return None
async def authenticate_github_user_token(access_token: str):
if not access_token:
logger.warning('No GitHub User ID provided')
return None
gh_service = SaaSGitHubService(token=SecretStr(access_token))
try:
user: GitHubUser = await gh_service.get_user()
if is_user_allowed(user.login):
return user
return None
except: # noqa: E722
logger.warning("GitHub user doens't have valid token")
return None