""" Example: Import credentials from a client project directory. This script demonstrates a real-world use case for the credential scanner: importing credentials from a client's project directory into the ClaudeTools credential vault with automatic encryption. Usage: python example_credential_import.py /path/to/client/project [--client-id UUID] """ import argparse import logging import sys from pathlib import Path from api.database import SessionLocal from api.utils.credential_scanner import ( scan_for_credential_files, parse_credential_file, import_credentials_to_db, scan_and_import_credentials, ) # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) def preview_credentials(base_path: str): """Preview credentials that would be imported without actually importing.""" logger.info(f"Scanning for credentials in: {base_path}") # Find credential files files = scan_for_credential_files(base_path) if not files: logger.warning("No credential files found") return [] logger.info(f"\nFound {len(files)} credential file(s):") for file_path in files: logger.info(f" - {file_path}") # Parse and preview all_credentials = [] for file_path in files: credentials = parse_credential_file(file_path) all_credentials.extend(credentials) logger.info(f"\n{Path(file_path).name}:") for cred in credentials: logger.info(f" Service: {cred.get('service_name')}") logger.info(f" Type: {cred.get('credential_type')}") if cred.get('username'): logger.info(f" Username: {cred.get('username')}") logger.info("") logger.info(f"Total credentials found: {len(all_credentials)}") return all_credentials def import_with_confirmation(base_path: str, client_id: str = None): """Import credentials with user confirmation.""" # Preview first credentials = preview_credentials(base_path) if not credentials: logger.info("No credentials to import") return # Ask for confirmation logger.info("\n" + "=" * 60) response = input(f"Import {len(credentials)} credential(s) to database? (yes/no): ") if response.lower() not in ['yes', 'y']: logger.info("Import cancelled") return # Import to database db = SessionLocal() try: logger.info("\nImporting credentials...") results = scan_and_import_credentials( base_path=base_path, db=db, client_id=client_id, user_id="manual_import", ip_address=None ) logger.info("\n" + "=" * 60) logger.info("IMPORT COMPLETE") logger.info("=" * 60) logger.info(f"Files scanned: {results['files_found']}") logger.info(f"Credentials parsed: {results['credentials_parsed']}") logger.info(f"Credentials imported: {results['credentials_imported']}") if results['credentials_imported'] < results['credentials_parsed']: logger.warning( f"Warning: {results['credentials_parsed'] - results['credentials_imported']} " "credential(s) failed to import. Check logs for details." ) except Exception as e: logger.error(f"Import failed: {str(e)}", exc_info=True) raise finally: db.close() def main(): """Main entry point.""" parser = argparse.ArgumentParser( description="Import credentials from a directory into ClaudeTools credential vault" ) parser.add_argument( 'path', type=str, help='Path to directory containing credential files' ) parser.add_argument( '--client-id', type=str, help='UUID of client to associate credentials with (optional)', default=None ) parser.add_argument( '--preview', action='store_true', help='Preview credentials without importing' ) args = parser.parse_args() # Validate path path = Path(args.path) if not path.exists(): logger.error(f"Path does not exist: {args.path}") sys.exit(1) if not path.is_dir(): logger.error(f"Path is not a directory: {args.path}") sys.exit(1) # Preview or import if args.preview: preview_credentials(str(path)) else: import_with_confirmation(str(path), args.client_id) if __name__ == "__main__": main()