""" Flask Web Application for InklyAI Signature Verification UI """ from flask import Flask, render_template, request, jsonify, send_from_directory import os import uuid from datetime import datetime import logging from werkzeug.utils import secure_filename from agentai_integration import AgentAISignatureManager, AgentAISignatureAPI from src.models.siamese_network import SignatureVerifier from src.data.preprocessing import SignaturePreprocessor # Initialize Flask app app = Flask(__name__) app.config['SECRET_KEY'] = 'inklyai-secret-key-2024' app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size # Setup logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Initialize signature manager signature_manager = AgentAISignatureManager( threshold=0.75, device='auto' ) # Initialize API wrapper api = AgentAISignatureAPI(signature_manager) # Create upload directories UPLOAD_FOLDER = 'uploads' REFERENCE_FOLDER = 'uploads/reference' VERIFICATION_FOLDER = 'uploads/verification' os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(REFERENCE_FOLDER, exist_ok=True) os.makedirs(VERIFICATION_FOLDER, exist_ok=True) # Allowed file extensions ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'tiff'} def allowed_file(filename): """Check if file extension is allowed.""" return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS def save_uploaded_file(file, folder): """Save uploaded file and return the path.""" if file and allowed_file(file.filename): filename = secure_filename(file.filename) # Add timestamp to avoid conflicts name, ext = os.path.splitext(filename) filename = f"{name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}{ext}" filepath = os.path.join(folder, filename) file.save(filepath) return filepath return None @app.route('/') def index(): """Main page with signature verification UI.""" return render_template('index.html') @app.route('/agents') def agents(): """Agent management page.""" return render_template('agents.html') @app.route('/api/agents', methods=['GET']) def get_agents(): """Get list of registered agents.""" try: agents = [] for agent_id, agent_signature in signature_manager.agent_signatures.items(): agents.append({ 'agent_id': agent_id, 'created_at': agent_signature.created_at.isoformat(), 'last_verified': agent_signature.last_verified.isoformat() if agent_signature.last_verified else None, 'verification_count': agent_signature.verification_count, 'is_active': agent_signature.is_active }) return jsonify({ 'success': True, 'agents': agents, 'total_agents': len(agents) }) except Exception as e: logger.error(f"Error getting agents: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 @app.route('/api/register-agent', methods=['POST']) def register_agent(): """Register a new agent with signature template.""" try: if 'signature_template' not in request.files: return jsonify({ 'success': False, 'error': 'No signature template file provided' }), 400 file = request.files['signature_template'] agent_id = request.form.get('agent_id') if not agent_id: return jsonify({ 'success': False, 'error': 'Agent ID is required' }), 400 # Save the signature template filepath = save_uploaded_file(file, REFERENCE_FOLDER) if not filepath: return jsonify({ 'success': False, 'error': 'Invalid file type. Please upload an image file.' }), 400 # Register the agent success = signature_manager.register_agent_signature(agent_id, filepath) if success: return jsonify({ 'success': True, 'agent_id': agent_id, 'message': 'Agent registered successfully' }) else: return jsonify({ 'success': False, 'error': 'Failed to register agent' }), 400 except Exception as e: logger.error(f"Error registering agent: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 @app.route('/api/verify', methods=['POST']) def verify_signatures(): """Verify two signatures.""" try: if 'signature1' not in request.files or 'signature2' not in request.files: return jsonify({ 'success': False, 'error': 'Both signature files are required' }), 400 agent_id = request.form.get('agent_id') if not agent_id: return jsonify({ 'success': False, 'error': 'Agent ID is required' }), 400 # Save uploaded files file1 = request.files['signature1'] file2 = request.files['signature2'] file1_path = save_uploaded_file(file1, VERIFICATION_FOLDER) file2_path = save_uploaded_file(file2, VERIFICATION_FOLDER) if not file1_path or not file2_path: return jsonify({ 'success': False, 'error': 'Invalid file types. Please upload image files.' }), 400 # Verify signatures similarity, is_genuine = signature_manager.verifier.verify_signatures( file1_path, file2_path, threshold=signature_manager.threshold ) # Calculate confidence confidence = similarity # Simple confidence calculation # Create verification result verification_id = str(uuid.uuid4())[:12] result = { 'success': True, 'is_verified': is_genuine, 'similarity_score': float(similarity), 'confidence': float(confidence), 'verification_id': verification_id, 'timestamp': datetime.now().isoformat(), 'agent_id': agent_id } # Log verification logger.info(f"Verification completed: {result}") return jsonify(result) except Exception as e: logger.error(f"Error verifying signatures: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 @app.route('/api/verify-agent', methods=['POST']) def verify_agent_signature(): """Verify signature against registered agent template.""" try: if 'signature_image' not in request.files: return jsonify({ 'success': False, 'error': 'Signature image file is required' }), 400 agent_id = request.form.get('agent_id') if not agent_id: return jsonify({ 'success': False, 'error': 'Agent ID is required' }), 400 # Check if agent exists if agent_id not in signature_manager.agent_signatures: return jsonify({ 'success': False, 'error': 'Agent not found' }), 404 # Save uploaded file file = request.files['signature_image'] file_path = save_uploaded_file(file, VERIFICATION_FOLDER) if not file_path: return jsonify({ 'success': False, 'error': 'Invalid file type. Please upload an image file.' }), 400 # Verify against agent template result = signature_manager.verify_agent_signature(agent_id, file_path) return jsonify({ 'success': True, 'is_verified': result.is_verified, 'similarity_score': result.similarity_score, 'confidence': result.confidence, 'verification_id': result.verification_id, 'timestamp': result.timestamp.isoformat(), 'agent_id': agent_id }) except Exception as e: logger.error(f"Error verifying agent signature: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 @app.route('/api/stats', methods=['GET']) def get_stats(): """Get verification statistics.""" try: stats = {} for agent_id in signature_manager.agent_signatures.keys(): agent_stats = signature_manager.get_agent_verification_stats(agent_id) stats[agent_id] = agent_stats return jsonify({ 'success': True, 'stats': stats }) except Exception as e: logger.error(f"Error getting stats: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 @app.route('/api/agent-stats/', methods=['GET']) def get_agent_stats(agent_id): """Get statistics for a specific agent.""" try: stats = signature_manager.get_agent_verification_stats(agent_id) return jsonify({ 'success': True, 'agent_id': agent_id, 'stats': stats }) except Exception as e: logger.error(f"Error getting agent stats: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 @app.route('/api/deactivate-agent/', methods=['POST']) def deactivate_agent(agent_id): """Deactivate an agent.""" try: success = signature_manager.deactivate_agent(agent_id) return jsonify({ 'success': success, 'agent_id': agent_id, 'action': 'deactivated' }) except Exception as e: logger.error(f"Error deactivating agent: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 @app.route('/api/reactivate-agent/', methods=['POST']) def reactivate_agent(agent_id): """Reactivate an agent.""" try: success = signature_manager.reactivate_agent(agent_id) return jsonify({ 'success': success, 'agent_id': agent_id, 'action': 'reactivated' }) except Exception as e: logger.error(f"Error reactivating agent: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 @app.route('/api/health', methods=['GET']) def health_check(): """Health check endpoint.""" return jsonify({ 'status': 'healthy', 'timestamp': datetime.now().isoformat(), 'service': 'InklyAI Web Application', 'agents_registered': len(signature_manager.agent_signatures) }) @app.errorhandler(413) def too_large(e): """Handle file too large error.""" return jsonify({ 'success': False, 'error': 'File too large. Maximum size is 16MB.' }), 413 @app.errorhandler(404) def not_found(e): """Handle 404 errors.""" return jsonify({ 'success': False, 'error': 'Endpoint not found' }), 404 @app.errorhandler(500) def internal_error(e): """Handle 500 errors.""" return jsonify({ 'success': False, 'error': 'Internal server error' }), 500 def initialize_demo_agents(): """Initialize demo agents if sample data exists.""" try: # Register demo agents if sample data exists demo_agents = [ ('Agent_01', 'data/samples/john_doe_1.png'), ('Agent_02', 'data/samples/jane_smith_1.png'), ('Agent_03', 'data/samples/bob_wilson_1.png'), ('Agent_04', 'data/samples/alice_brown_1.png') ] for agent_id, signature_template in demo_agents: if os.path.exists(signature_template): signature_manager.register_agent_signature(agent_id, signature_template) logger.info(f"Registered agent: {agent_id}") logger.info("Demo agents initialized successfully") except Exception as e: logger.warning(f"Could not initialize demo agents: {e}") if __name__ == '__main__': # Initialize demo agents initialize_demo_agents() # Start the web application port = int(os.environ.get('PORT', 8080)) # Use port 8080 instead of 5000 debug = os.environ.get('DEBUG', 'False').lower() == 'true' logger.info(f"Starting InklyAI Web Application on port {port}") logger.info(f"Access the application at: http://localhost:{port}") app.run(host='0.0.0.0', port=port, debug=debug)