import { exec } from 'child_process'; import { promisify } from 'util'; import { requireApiAuth, type User } from '../../utils/apiAuth.ts'; import type { APIContext } from 'astro'; const execAsync = promisify(exec); interface DiskSpaceResponse { total: number; used: number; available: number; usedPercent: number; totalFormatted: string; usedFormatted: string; availableFormatted: string; } export async function GET({ request }: APIContext): Promise { // Check authentication const { user, error: authError, setCookieHeader } = await requireApiAuth(request); if (authError) return authError; // Check authorization - must have 'admin' or 'trip' role const userRoles = user?.roles || []; const hasAccess = userRoles.includes('admin') || userRoles.includes('trip'); if (!hasAccess) { return new Response(JSON.stringify({ error: 'Forbidden', message: 'Insufficient permissions. Requires admin or trip role.' }), { status: 403, headers: { 'Content-Type': 'application/json' }, }); } try { // Get disk space for root filesystem const { stdout } = await execAsync("df -B1 / | tail -1 | awk '{print $2,$3,$4}'"); const [total, used, available] = stdout.trim().split(/\s+/).map(Number); if (!total || !available) { throw new Error('Failed to parse disk space'); } const usedPercent = Math.round((used / total) * 100); const responseHeaders = { 'Content-Type': 'application/json' }; if (setCookieHeader) { responseHeaders['Set-Cookie'] = setCookieHeader; } return new Response(JSON.stringify({ total, used, available, usedPercent, // Human-readable versions totalFormatted: formatBytes(total), usedFormatted: formatBytes(used), availableFormatted: formatBytes(available), }), { status: 200, headers: responseHeaders, }); } catch (err) { console.error('Error getting disk space:', err); return new Response(JSON.stringify({ error: 'Failed to get disk space' }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); } } function formatBytes(bytes: number): string { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }