// server/api/users/[id].ts // Simple in-memory rate limiter const rateLimitMap = new Map(); const RATE_LIMIT_WINDOW = 60000; // 1 minute const RATE_LIMIT_MAX = 10; // 10 requests per minute per admin function checkRateLimit(adminToken: string): boolean { const now = Date.now(); const limit = rateLimitMap.get(adminToken); if (!limit || now > limit.resetTime) { rateLimitMap.set(adminToken, { count: 1, resetTime: now + RATE_LIMIT_WINDOW }); return true; } if (limit.count >= RATE_LIMIT_MAX) { return false; } limit.count++; return true; } export default defineEventHandler(async (event) => { const method = event.node.req.method; const userId = getRouterParam(event, 'id'); // We use Nitro's built-in storage. // 'polls' is the storage namespace. const storage = useStorage('users'); if (!userId) { throw createError({ statusCode: 400, statusMessage: 'User ID required' }); } // GET: Fetch the saved Yjs document state if (method === 'GET') { const data = await storage.getItem(`user:${userId}`); // Return the array of numbers (or null if it doesn't exist yet) return { public_key: data }; } // POST: Save a new Yjs document state if (method === 'POST') { // Check for authentication const authHeader = getHeader(event, 'authorization'); const adminApiKey = process.env.ADMIN_API_KEY || 'default-admin-key-change-in-production'; if (!authHeader || !authHeader.startsWith('Bearer ')) { throw createError({ statusCode: 401, statusMessage: 'Authorization header required' }); } const token = authHeader.replace('Bearer ', ''); if (token !== adminApiKey) { throw createError({ statusCode: 403, statusMessage: 'Invalid or expired token' }); } // Check rate limiting if (!checkRateLimit(token)) { throw createError({ statusCode: 429, statusMessage: 'Rate limit exceeded. Try again later.' }); } const body = await readBody(event); if (body.public_key) { const data = await storage.getItem(`user:${userId}`); if (data == undefined || data == null) { // Save the binary update (sent as an array of numbers) to storage await storage.setItem(`user:${userId}`, body.public_key); console.log("New User created: " + userId) console.log("Public Key: " + body.public_key); return { success: true }; } throw createError({ statusCode: 400, statusMessage: 'User already exists.' }); } throw createError({ statusCode: 400, statusMessage: 'Invalid update payload' }); } });