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
22 lines
1.1 KiB
C#
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);
|
|
}
|