|
3 | 3 | import { requireAdmin } from "@/lib/admin" |
4 | 4 | import { prisma } from "@/lib/prisma" |
5 | 5 |
|
| 6 | +/** |
| 7 | + * Get Jellyfin libraries for invite creation |
| 8 | + */ |
| 9 | +export async function getJellyfinLibraries() { |
| 10 | + await requireAdmin() |
| 11 | + |
| 12 | + try { |
| 13 | + const jellyfinServer = await prisma.jellyfinServer.findFirst({ |
| 14 | + where: { isActive: true }, |
| 15 | + }) |
| 16 | + |
| 17 | + if (!jellyfinServer) { |
| 18 | + return { success: false, error: "No active Jellyfin server configured" } |
| 19 | + } |
| 20 | + |
| 21 | + const { getJellyfinLibraries: fetchLibraries } = await import("@/lib/connections/jellyfin") |
| 22 | + |
| 23 | + const result = await fetchLibraries({ |
| 24 | + url: jellyfinServer.url, |
| 25 | + apiKey: jellyfinServer.apiKey, |
| 26 | + }) |
| 27 | + |
| 28 | + if (!result.success) { |
| 29 | + return { success: false, error: result.error } |
| 30 | + } |
| 31 | + |
| 32 | + // Transform to simpler format for UI |
| 33 | + const libraries = (result.data || []).map((lib) => ({ |
| 34 | + id: lib.ItemId, |
| 35 | + name: lib.Name, |
| 36 | + type: lib.CollectionType || "unknown", |
| 37 | + })) |
| 38 | + |
| 39 | + return { success: true, data: libraries } |
| 40 | + } catch (error) { |
| 41 | + if (error instanceof Error) { |
| 42 | + return { success: false, error: error.message } |
| 43 | + } |
| 44 | + return { success: false, error: "Failed to fetch Jellyfin libraries" } |
| 45 | + } |
| 46 | +} |
| 47 | + |
6 | 48 | /** |
7 | 49 | * Update Plex server configuration (admin only) |
8 | 50 | */ |
@@ -425,6 +467,108 @@ export async function updatePrometheus(data: { name: string; url: string; query: |
425 | 467 | } |
426 | 468 | } |
427 | 469 |
|
| 470 | +/** |
| 471 | + * Update Jellyfin server configuration (admin only) |
| 472 | + */ |
| 473 | +export async function updateJellyfinServer(data: { name: string; url: string; apiKey: string; publicUrl?: string }) { |
| 474 | + await requireAdmin() |
| 475 | + |
| 476 | + try { |
| 477 | + const { jellyfinServerSchema } = await import("@/lib/validations/jellyfin") |
| 478 | + const { testJellyfinConnection, getJellyfinServerInfo } = await import("@/lib/connections/jellyfin") |
| 479 | + const { revalidatePath } = await import("next/cache") |
| 480 | + |
| 481 | + const validated = jellyfinServerSchema.parse(data) |
| 482 | + |
| 483 | + // Test connection before saving |
| 484 | + const connectionTest = await testJellyfinConnection(validated) |
| 485 | + if (!connectionTest.success) { |
| 486 | + return { success: false, error: connectionTest.error || "Failed to connect to Jellyfin server" } |
| 487 | + } |
| 488 | + |
| 489 | + // Get server info to retrieve admin user ID (optional) |
| 490 | + let adminUserId: string | undefined |
| 491 | + const serverInfoResult = await getJellyfinServerInfo(validated) |
| 492 | + if (serverInfoResult.success && serverInfoResult.data) { |
| 493 | + // The API key is associated with an admin user, but we can't easily get their ID |
| 494 | + // from just the server info. This can be populated later if needed. |
| 495 | + adminUserId = undefined |
| 496 | + } |
| 497 | + |
| 498 | + await prisma.$transaction(async (tx) => { |
| 499 | + // Deactivate existing active server |
| 500 | + await tx.jellyfinServer.updateMany({ |
| 501 | + where: { isActive: true }, |
| 502 | + data: { isActive: false }, |
| 503 | + }) |
| 504 | + |
| 505 | + // Update or create server |
| 506 | + const existing = await tx.jellyfinServer.findFirst({ |
| 507 | + where: { |
| 508 | + url: validated.url, |
| 509 | + }, |
| 510 | + }) |
| 511 | + |
| 512 | + if (existing) { |
| 513 | + await tx.jellyfinServer.update({ |
| 514 | + where: { id: existing.id }, |
| 515 | + data: { |
| 516 | + name: validated.name, |
| 517 | + url: validated.url, |
| 518 | + apiKey: validated.apiKey, |
| 519 | + publicUrl: validated.publicUrl, |
| 520 | + adminUserId, |
| 521 | + isActive: true, |
| 522 | + }, |
| 523 | + }) |
| 524 | + } else { |
| 525 | + await tx.jellyfinServer.create({ |
| 526 | + data: { |
| 527 | + name: validated.name, |
| 528 | + url: validated.url, |
| 529 | + apiKey: validated.apiKey, |
| 530 | + publicUrl: validated.publicUrl, |
| 531 | + adminUserId, |
| 532 | + isActive: true, |
| 533 | + }, |
| 534 | + }) |
| 535 | + } |
| 536 | + }) |
| 537 | + |
| 538 | + revalidatePath("/admin/settings") |
| 539 | + return { success: true } |
| 540 | + } catch (error) { |
| 541 | + if (error instanceof Error) { |
| 542 | + return { success: false, error: error.message } |
| 543 | + } |
| 544 | + return { success: false, error: "Failed to update Jellyfin server configuration" } |
| 545 | + } |
| 546 | +} |
| 547 | + |
| 548 | +/** |
| 549 | + * Delete Jellyfin server configuration (admin only) |
| 550 | + */ |
| 551 | +export async function deleteJellyfinServer() { |
| 552 | + await requireAdmin() |
| 553 | + |
| 554 | + try { |
| 555 | + const { revalidatePath } = await import("next/cache") |
| 556 | + |
| 557 | + await prisma.jellyfinServer.updateMany({ |
| 558 | + where: { isActive: true }, |
| 559 | + data: { isActive: false }, |
| 560 | + }) |
| 561 | + |
| 562 | + revalidatePath("/admin/settings") |
| 563 | + return { success: true } |
| 564 | + } catch (error) { |
| 565 | + if (error instanceof Error) { |
| 566 | + return { success: false, error: error.message } |
| 567 | + } |
| 568 | + return { success: false, error: "Failed to delete Jellyfin server configuration" } |
| 569 | + } |
| 570 | +} |
| 571 | + |
428 | 572 | /** |
429 | 573 | * Delete Prometheus configuration (admin only) |
430 | 574 | */ |
|
0 commit comments