/** * API Route: Register an anonymous plant * POST /api/plants/register-anonymous * * This endpoint allows for privacy-preserving plant registration */ import type { NextApiRequest, NextApiResponse } from 'next'; import { getBlockchain, saveBlockchain } from '../../../lib/blockchain/manager'; import { PlantData } from '../../../lib/blockchain/types'; import { generateAnonymousId, generateWalletAddress, obfuscateLocation, generateAnonymousPlantName, createAnonymousContact, PrivacySettings, } from '../../../lib/privacy/anonymity'; import { getTorService } from '../../../lib/services/tor'; interface AnonymousPlantRequest { commonName: string; scientificName?: string; species?: string; genus?: string; family?: string; location: { latitude: number; longitude: number; }; privacySettings: PrivacySettings; pseudonym?: string; encryptionKey?: string; } export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); } try { const requestData: AnonymousPlantRequest = req.body; // Validate required fields if (!requestData.commonName || !requestData.location || !requestData.privacySettings) { return res.status(400).json({ error: 'Missing required fields: commonName, location, privacySettings', }); } const { location, privacySettings } = requestData; // Check if request came through Tor const torService = getTorService(); const isTorConnection = torService.isRequestFromTor(req.headers); // Generate anonymous identifiers const anonymousUserId = generateAnonymousId(); const walletAddress = generateWalletAddress(); const plantId = `plant-${generateAnonymousId()}`; // Obfuscate location based on privacy settings const fuzzyLocation = obfuscateLocation( location.latitude, location.longitude, privacySettings.locationPrivacy ); // Determine display name based on privacy settings let displayName: string; if (privacySettings.identityPrivacy === 'anonymous') { displayName = 'Anonymous Grower'; } else if (privacySettings.identityPrivacy === 'pseudonym' && requestData.pseudonym) { displayName = requestData.pseudonym; } else { displayName = `Grower-${anonymousUserId.substring(0, 8)}`; } // Create anonymous contact const anonymousEmail = createAnonymousContact( anonymousUserId, requestData.encryptionKey || 'default-key' ); // Build plant data with privacy protections const plantData: PlantData = { id: plantId, commonName: privacySettings.sharePlantDetails ? requestData.commonName : generateAnonymousPlantName(requestData.commonName, 0), scientificName: privacySettings.sharePlantDetails ? requestData.scientificName : undefined, species: privacySettings.sharePlantDetails ? requestData.species : undefined, genus: privacySettings.sharePlantDetails ? requestData.genus : undefined, family: privacySettings.sharePlantDetails ? requestData.family : undefined, propagationType: 'original', generation: 0, plantedDate: new Date().toISOString(), status: 'growing', location: { latitude: fuzzyLocation.latitude, longitude: fuzzyLocation.longitude, address: fuzzyLocation.displayName, city: privacySettings.locationPrivacy !== 'hidden' ? 'Privacy Protected' : undefined, country: privacySettings.locationPrivacy === 'country' ? 'Anonymous Region' : undefined, }, owner: { id: anonymousUserId, name: displayName, email: anonymousEmail, walletAddress: walletAddress, }, childPlants: [], registeredAt: new Date().toISOString(), updatedAt: new Date().toISOString(), notes: privacySettings.anonymousMode ? 'Registered anonymously via privacy mode' : undefined, }; const blockchain = getBlockchain(); // Register the plant const block = blockchain.registerPlant(plantData); // Save blockchain saveBlockchain(); // Prepare response with privacy info res.status(201).json({ success: true, plant: block.plant, privacy: { anonymousId: anonymousUserId, walletAddress: walletAddress, locationAccuracy: fuzzyLocation.accuracy, torConnection: isTorConnection, privacyLevel: privacySettings.locationPrivacy, }, block: { index: block.index, hash: block.hash, timestamp: block.timestamp, }, message: 'Plant registered anonymously', warning: !isTorConnection ? 'For maximum privacy, consider accessing through Tor network' : null, }); } catch (error: any) { console.error('Error registering anonymous plant:', error); res.status(500).json({ error: error.message || 'Internal server error' }); } }