fix(template-engine): resolve TemplateEngine-001/003/004/005, re-triage 002 — recursive composed flattening, fixed-field guard, alarm script refs, dead collision query
This commit is contained in:
@@ -51,15 +51,12 @@ public class TemplateService
|
||||
FolderId = folderId
|
||||
};
|
||||
|
||||
// Check acyclicity (inheritance) — for new templates this is mostly a parent-exists check,
|
||||
// but we validate anyway for consistency
|
||||
if (parentTemplateId.HasValue)
|
||||
{
|
||||
var allTemplates = await _repository.GetAllTemplatesAsync(cancellationToken);
|
||||
// The new template doesn't exist yet, so we simulate by adding it to the list
|
||||
// with a temporary ID. Since it has no children yet, the only cycle would be
|
||||
// if parentTemplateId somehow pointed at itself (already handled above).
|
||||
}
|
||||
// No collision or acyclicity check is needed here: a freshly created
|
||||
// template has no members of its own, the parent (validated above to
|
||||
// exist) was already collision-checked when its members were added,
|
||||
// and a brand-new child cannot be an ancestor of its parent. Naming
|
||||
// collisions are enforced on every member-mutating call (AddAttribute,
|
||||
// AddAlarm, AddScript, AddComposition) and on rename in UpdateTemplate.
|
||||
|
||||
await _repository.AddTemplateAsync(template, cancellationToken);
|
||||
await _auditService.LogAsync(user, "Create", "Template", "0", name, template, cancellationToken);
|
||||
@@ -281,17 +278,19 @@ public class TemplateService
|
||||
if (lockError != null)
|
||||
return Result<TemplateAttribute>.Failure(lockError);
|
||||
|
||||
// Validate fixed-field granularity
|
||||
// Validate fixed-field granularity. DataType and DataSourceReference are
|
||||
// fixed by the defining level for every attribute — locked or not — so
|
||||
// the error is always honoured (a locked attribute is already rejected
|
||||
// earlier inside the helper).
|
||||
var granularityError = LockEnforcer.ValidateAttributeOverride(existing, proposed);
|
||||
if (granularityError != null && existing.IsLocked)
|
||||
if (granularityError != null)
|
||||
return Result<TemplateAttribute>.Failure(granularityError);
|
||||
|
||||
// Apply overridable fields
|
||||
// Apply overridable fields. DataType / DataSourceReference are fixed and
|
||||
// are deliberately not copied from the proposed attribute.
|
||||
existing.Value = proposed.Value;
|
||||
existing.Description = proposed.Description;
|
||||
existing.IsLocked = proposed.IsLocked;
|
||||
existing.DataType = proposed.DataType;
|
||||
existing.DataSourceReference = proposed.DataSourceReference;
|
||||
if (template?.IsDerived == true)
|
||||
existing.IsInherited = proposed.IsInherited;
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user