8cdeadd6dd
PR 1 of 4 for the runtime service registry change. - Add Fernet encryption helper (services/secrets.py) with a required MANAGE_ENCRYPTION_KEY; validate it on startup. - Add closed integrations/ registry with Pydantic config + widget-config definitions for grafana, prometheus, jellyfin, nextcloud, and ssh_tasks. - Add services + service_task_runs tables and SettingsStore CRUD with cascade-delete (defensive until widgets carry service_id). - Add /api/services/types and /api/services/instances CRUD (encrypted secrets, secrets_set flags only; never plaintext). - Declare cryptography as a direct dependency. - Require MANAGE_ENCRYPTION_KEY in compose + .env.example + README. - Add 25 backend tests (registry, encryption, CRUD, cascade, task-run history). Verification: ruff clean; pytest 225 passed; frontend lint/build green.
48 lines
1.1 KiB
Python
48 lines
1.1 KiB
Python
"""Jellyfin service definition."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from media_library_viewer_api.integrations.base import (
|
|
SecretField,
|
|
ServiceConfigBase,
|
|
ServiceDefinition,
|
|
WidgetConfigBase,
|
|
widget_kind,
|
|
)
|
|
|
|
|
|
class JellyfinConfig(ServiceConfigBase):
|
|
"""Non-secret Jellyfin connection config."""
|
|
|
|
base_url: str
|
|
user_id: str = ""
|
|
timeout_seconds: int = 10
|
|
|
|
|
|
class JellyfinActivityWidgetConfig(WidgetConfigBase):
|
|
"""Live Jellyfin session activity."""
|
|
|
|
# No user-overridable fields; the service record carries user_id.
|
|
pass
|
|
|
|
|
|
DEFINITION = ServiceDefinition(
|
|
service_type="jellyfin",
|
|
name="Jellyfin",
|
|
description="Media server with live session activity.",
|
|
config_model=JellyfinConfig,
|
|
secret_fields=[
|
|
SecretField(key="api_key", label="API key", required=True),
|
|
],
|
|
widget_kinds=[
|
|
widget_kind(
|
|
kind="activity",
|
|
name="Activity",
|
|
description="Live sessions and idle users.",
|
|
model_cls=JellyfinActivityWidgetConfig,
|
|
default_config={},
|
|
refresh_interval_ms=30_000,
|
|
),
|
|
],
|
|
)
|