using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ZB.MOM.WW.OtOpcUa.Configuration.Migrations
{
///
/// #520 — NodeAcl.LdapGroup becomes NodeAcl.Principal. The OPC UA data plane is
/// machine-to-machine, so an ACL grant keys on an API-key principal (or the reserved
/// anonymous), not on an LDAP group. EF scaffolds this as RenameColumn/RenameIndex, so
/// existing rows survive.
///
///
/// ⚠️ The column is also read by dbo.sp_ComputeGenerationDiff, created in
/// V3Initial.StoredProcedures and never redefined since. A bare column rename leaves that
/// proc referencing a column that no longer exists — SQL Server does not validate a procedure
/// body at rename time, so the object keeps reporting healthy and fails at CALL time with
/// Invalid column name 'LdapGroup', silently breaking config-drift detection. The proc is
/// therefore re-emitted below in the same migration, body otherwise byte-identical. If you add or
/// rename a column on any table that proc checksums, it needs the same treatment.
///
public partial class RenameNodeAclLdapGroupToPrincipal : Migration
{
///
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "LdapGroup",
table: "NodeAcl",
newName: "Principal");
migrationBuilder.RenameIndex(
name: "UX_NodeAcl_GroupScope",
table: "NodeAcl",
newName: "UX_NodeAcl_PrincipalScope");
migrationBuilder.RenameIndex(
name: "IX_NodeAcl_Group",
table: "NodeAcl",
newName: "IX_NodeAcl_Principal");
migrationBuilder.Sql(ComputeGenerationDiff("Principal"));
}
///
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "Principal",
table: "NodeAcl",
newName: "LdapGroup");
migrationBuilder.RenameIndex(
name: "UX_NodeAcl_PrincipalScope",
table: "NodeAcl",
newName: "UX_NodeAcl_GroupScope");
migrationBuilder.RenameIndex(
name: "IX_NodeAcl_Principal",
table: "NodeAcl",
newName: "IX_NodeAcl_Group");
migrationBuilder.Sql(ComputeGenerationDiff("LdapGroup"));
}
///
/// dbo.sp_ComputeGenerationDiff re-emitted with the NodeAcl grantee column named by
/// . Kept as one parameterised template so Up and Down cannot
/// drift from each other, and so the diff shows exactly one token changing.
///
/// The NodeAcl grantee column name to checksum.
/// The CREATE OR ALTER PROCEDURE statement.
private static string ComputeGenerationDiff(string granteeColumn) => $@"
CREATE OR ALTER PROCEDURE dbo.sp_ComputeGenerationDiff
@FromGenerationId bigint,
@ToGenerationId bigint
AS
BEGIN
SET NOCOUNT ON;
-- @FromGenerationId / @ToGenerationId are ignored: the v3 config tables are single live-state
-- (no GenerationId column). Emit a current-state signature per row so the shape (TableName,
-- LogicalId, Sig) still round-trips through any legacy caller.
SELECT TableName, LogicalId, Sig FROM (
SELECT 'RawFolder' AS TableName, RawFolderId AS LogicalId, CHECKSUM(ClusterId, ParentRawFolderId, Name, SortOrder) AS Sig FROM dbo.RawFolder
UNION ALL
SELECT 'DriverInstance', DriverInstanceId, CHECKSUM(ClusterId, RawFolderId, Name, DriverType, Enabled, CONVERT(varchar(max), DriverConfig)) FROM dbo.DriverInstance
UNION ALL
SELECT 'Device', DeviceId, CHECKSUM(DriverInstanceId, Name, Enabled, CONVERT(varchar(max), DeviceConfig)) FROM dbo.Device
UNION ALL
SELECT 'TagGroup', TagGroupId, CHECKSUM(DeviceId, ParentTagGroupId, Name, SortOrder) FROM dbo.TagGroup
UNION ALL
SELECT 'Tag', TagId, CHECKSUM(DeviceId, TagGroupId, PollGroupId, Name, DataType, AccessLevel, WriteIdempotent, CONVERT(varchar(max), TagConfig)) FROM dbo.Tag
UNION ALL
SELECT 'Equipment', EquipmentId, CHECKSUM(EquipmentUuid, UnsLineId, Name, MachineCode, ZTag, SAPID, EquipmentClassRef, Manufacturer, Model, SerialNumber) FROM dbo.Equipment
UNION ALL
SELECT 'UnsTagReference', UnsTagReferenceId, CHECKSUM(EquipmentId, TagId, DisplayNameOverride, SortOrder) FROM dbo.UnsTagReference
UNION ALL
SELECT 'NodeAcl', NodeAclId, CHECKSUM(ClusterId, {granteeColumn}, ScopeKind, ScopeId, PermissionFlags, Notes) FROM dbo.NodeAcl
) AS inventory;
END
";
}
}