Files
immich-folio/app/api/admin/albums/route.ts
ralksta 9e52d7a0b8 feat: add visual admin panel with page builder and settings editor
- Add /admin route with password-protected visual page builder
- Page Builder: manage hero images, standalone albums, subpages, and sections
- Album Picker: browse all shared Immich albums with search and filtering
- Settings Editor: theme, grid, footer, legal, SEO configuration
- YAML service with atomic writes and automatic backups (content/.backups/)
- HMAC-signed admin sessions (24h expiry, HttpOnly cookies)
- API endpoints: /api/admin/{auth,gallery,settings,albums,reload}
- Enable with ADMIN_PASSWORD env var; disabled by default
- invalidateConfigCache() export for hot-reload after saves
2026-05-29 17:04:37 +02:00

68 lines
2.1 KiB
TypeScript

import { NextResponse } from 'next/server';
import { isAdminAuthenticated, isAdminEnabled } from '@/lib/admin/auth';
import { getConfig } from '@/lib/config';
interface ImmichAlbumSummary {
id: string;
albumName: string;
description: string;
albumThumbnailAssetId: string | null;
assetCount: number;
createdAt: string;
updatedAt: string;
}
/** GET: List ALL shared Immich albums (not just allowlisted ones). */
export async function GET() {
if (!isAdminEnabled()) {
return NextResponse.json({ error: 'Admin not enabled' }, { status: 403 });
}
if (!(await isAdminAuthenticated())) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const config = getConfig();
if (config.needsSetup) {
return NextResponse.json({ error: 'Immich not configured' }, { status: 503 });
}
try {
const res = await fetch(`${config.immich.apiUrl}/albums?shared=true`, {
headers: {
'x-api-key': config.immich.apiKey,
Accept: 'application/json',
},
});
if (!res.ok) {
return NextResponse.json({ error: `Immich API returned ${res.status}` }, { status: 502 });
}
const albums = (await res.json()) as ImmichAlbumSummary[];
// Mark which albums are already configured
const configuredIds = new Set(config.albums);
const enriched = albums.map((album) => ({
id: album.id,
albumName: album.albumName,
description: album.description || '',
thumbnailAssetId: album.albumThumbnailAssetId,
assetCount: album.assetCount,
createdAt: album.createdAt,
updatedAt: album.updatedAt,
isConfigured: configuredIds.has(album.id),
}));
// Sort: configured first, then by name
enriched.sort((a, b) => {
if (a.isConfigured !== b.isConfigured) return a.isConfigured ? -1 : 1;
return a.albumName.localeCompare(b.albumName);
});
return NextResponse.json({ albums: enriched });
} catch (err) {
console.error('[Admin] Failed to fetch albums from Immich:', err);
return NextResponse.json({ error: 'Failed to connect to Immich' }, { status: 502 });
}
}