Files
ersatztv/ErsatzTV.Core/Graphics/GraphicsElementDefaults.cs
T
timothyandClaude Fable 5.1 900dac9832 fix(568): reject unknown channel graphicsElementIds with 422; discriminate builtIn by seeded path not filename
UpdateChannelHandler.Validate never checked incoming graphicsElementIds against
GraphicsElements, so PUT /api/v1/channels/{id} with a non-existent id hit
FK_ChannelGraphicsElement_GraphicsElement_GraphicsElementId at SaveChangesAsync
and surfaced as an unhandled 500. Add GraphicsElementIdsMustExist, following the
existing FFmpegProfileMustExist/WatermarkMustExist/FillerPresetMustExist shape,
so an unknown id now returns 422 for parity with every other FK field on this
full-replace DTO.

GetAllGraphicsElementsForApiHandler and GraphicsElementSeeder.GetBuiltInElementId
keyed builtIn off Path.GetFileName(e.Path) == OnNowNextFileName -- folder-agnostic,
so a user element named exactly on-now-next.yml in any other template folder would
also report builtIn:true. Both now compare against
GraphicsElementDefaults.OnNowNextSeededPath, the full path the seeder actually
writes to.

Follow-up from the #74 whole-branch review (2026-07-22), deferred as
data-safe/not SPA-reachable.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV
2026-09-05 21:35:14 +02:00

22 lines
1.1 KiB
C#

using System.IO;
namespace ErsatzTV.Core.Graphics;
public static class GraphicsElementDefaults
{
// Built-in "On Now / Next" text element; identity is by filename, never by user-editable Name.
public const string OnNowNextFileName = "on-now-next.yml";
// Display name only. Never use it for identity -- that is the filename above (#67 / #74).
public const string OnNowNextName = "On Now / Next";
// The full path the seeder writes the built-in template to. A `builtIn` discriminator must
// match THIS, not `Path.GetFileName(...) == OnNowNextFileName` -- a filename-only comparison is
// case-sensitive-by-accident and folder-agnostic: a user element named exactly `on-now-next.yml`
// in any of the other four template folders (image/motion/subtitle/script) would also report
// `builtIn:true` (#568). `Kind == Text` alone does not close this either, since a second text
// template could share the filename in principle.
public static string OnNowNextSeededPath =>
Path.Combine(FileSystemLayout.GraphicsElementsTextTemplatesFolder, OnNowNextFileName);
}