From 4e00a9bbe4fd6cc5ebd4bec47e3c029973823046 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 29 Jan 2024 12:55:50 -0500 Subject: [PATCH] Fixed a serialization issue with PermissionInfo This is a work in progress --- .../Security/Permissions/PermissionInfo.cs | 53 +++++---- .../Permissions/PermissionInfoBase.cs | 47 ++++---- .../DotNetNuke.Tests.Core.csproj | 2 + .../Permissions/PermissionInfoBaseTests.cs | 45 ++++++++ .../Permissions/PermissionInfoTests.cs | 108 ++++++++++++++++++ 5 files changed, 212 insertions(+), 43 deletions(-) create mode 100644 DNN Platform/Tests/DotNetNuke.Tests.Core/Security/Permissions/PermissionInfoBaseTests.cs create mode 100644 DNN Platform/Tests/DotNetNuke.Tests.Core/Security/Permissions/PermissionInfoTests.cs diff --git a/DNN Platform/Library/Security/Permissions/PermissionInfo.cs b/DNN Platform/Library/Security/Permissions/PermissionInfo.cs index 6a829607cb9..ebfc2ad17b5 100644 --- a/DNN Platform/Library/Security/Permissions/PermissionInfo.cs +++ b/DNN Platform/Library/Security/Permissions/PermissionInfo.cs @@ -18,28 +18,33 @@ namespace DotNetNuke.Security.Permissions /// PermissionInfo provides the Entity Layer for Permissions. [Serializable] public class PermissionInfo : BaseEntityInfo, IPermissionDefinitionInfo - { - /// + { + private int moduleDefId; + private int permissionId; + + /// [XmlIgnore] [JsonIgnore] - [Obsolete($"Deprecated in DotNetNuke 9.13.1. Use {nameof(IPermissionDefinitionInfo)}.{nameof(IPermissionDefinitionInfo.ModuleDefId)} instead. Scheduled for removal in v11.0.0.")] + [Obsolete($"Deprecated in DotNetNuke 9.13.1. Use {nameof(ModuleDefId)} instead. Scheduled for removal in v11.0.0.")] + [CLSCompliant(false)] public int ModuleDefID { - get => ((IPermissionDefinitionInfo)this).ModuleDefId; - set => ((IPermissionDefinitionInfo)this).ModuleDefId = value; + get => this.moduleDefId; + set => this.moduleDefId = value; } /// [XmlElement("permissioncode")] public string PermissionCode { get; set; } - /// - [XmlElement("permissionid")] - [Obsolete($"Deprecated in DotNetNuke 9.13.1. Use {nameof(IPermissionDefinitionInfo)}.{nameof(IPermissionDefinitionInfo.PermissionId)} instead. Scheduled for removal in v11.0.0.")] + /// + [XmlIgnore] + [Obsolete($"Deprecated in DotNetNuke 9.13.1. Use {nameof(PermissionId)} instead. Scheduled for removal in v11.0.0.")] + [CLSCompliant(false)] public int PermissionID { - get => ((IPermissionDefinitionInfo)this).PermissionId; - set => ((IPermissionDefinitionInfo)this).PermissionId = value; + get => this.permissionId; + set => this.permissionId = value; } /// @@ -54,25 +59,31 @@ public int PermissionID /// [XmlIgnore] [JsonIgnore] - int IPermissionDefinitionInfo.ModuleDefId { get; set; } + public int ModuleDefId + { + get => this.moduleDefId; + set => this.moduleDefId = value; + } /// - [XmlIgnore] - [JsonIgnore] - int IPermissionDefinitionInfo.PermissionId { get; set; } + [XmlElement("permissionid")] + public int PermissionId + { + get => this.permissionId; + set => this.permissionId = value; + } /// FillInternal fills a PermissionInfo from a Data Reader. /// The Data Reader to use. protected override void FillInternal(IDataReader dr) { base.FillInternal(dr); - - var @this = (IPermissionDefinitionInfo)this; - @this.PermissionId = Null.SetNullInteger(dr["PermissionID"]); - @this.ModuleDefId = Null.SetNullInteger(dr["ModuleDefID"]); - @this.PermissionCode = Null.SetNullString(dr["PermissionCode"]); - @this.PermissionKey = Null.SetNullString(dr["PermissionKey"]); - @this.PermissionName = Null.SetNullString(dr["PermissionName"]); + + this.permissionId = Null.SetNullInteger(dr["PermissionID"]); + this.moduleDefId = Null.SetNullInteger(dr["ModuleDefID"]); + this.PermissionCode = Null.SetNullString(dr["PermissionCode"]); + this.PermissionKey = Null.SetNullString(dr["PermissionKey"]); + this.PermissionName = Null.SetNullString(dr["PermissionName"]); } } } diff --git a/DNN Platform/Library/Security/Permissions/PermissionInfoBase.cs b/DNN Platform/Library/Security/Permissions/PermissionInfoBase.cs index c4815d27e98..1f5eada523d 100644 --- a/DNN Platform/Library/Security/Permissions/PermissionInfoBase.cs +++ b/DNN Platform/Library/Security/Permissions/PermissionInfoBase.cs @@ -76,19 +76,20 @@ public string DisplayName } } - /// - [XmlElement("roleid")] - [Obsolete($"Deprecated in DotNetNuke 9.13.1. Use {nameof(IPermissionInfo)}.{nameof(IPermissionInfo.RoleId)} instead. Scheduled for removal in v11.0.0.")] + /// + [XmlIgnore] + [Obsolete($"Deprecated in DotNetNuke 9.13.1. Use {nameof(RoleId)} instead. Scheduled for removal in v11.0.0.")] + [CLSCompliant(false)] public int RoleID { get { - return ((IPermissionInfo)this).RoleId; + return this.roleId; } set { - ((IPermissionInfo)this).RoleId = value; + this.roleId = value; } } @@ -107,19 +108,20 @@ public string RoleName } } - /// - [XmlElement("userid")] - [Obsolete($"Deprecated in DotNetNuke 9.13.1. Use {nameof(IPermissionInfo)}.{nameof(IPermissionInfo.UserId)} instead. Scheduled for removal in v11.0.0.")] + /// + [XmlIgnore] + [Obsolete($"Deprecated in DotNetNuke 9.13.1. Use {nameof(UserId)} instead. Scheduled for removal in v11.0.0.")] + [CLSCompliant(false)] public int UserID { get { - return ((IPermissionInfo)this).UserId; + return this.userId; } set { - ((IPermissionInfo)this).UserId = value; + this.userId = value; } } @@ -139,14 +141,16 @@ public string Username } /// - int IPermissionInfo.RoleId + [XmlElement("roleid")] + public int RoleId { get => this.roleId; set => this.roleId = value; } /// - int IPermissionInfo.UserId + [XmlElement("userid")] + public int UserId { get => this.userId; set => this.userId = value; @@ -159,22 +163,21 @@ protected override void FillInternal(IDataReader dr) // Call the base classes fill method to populate base class properties base.FillInternal(dr); - var @this = (IPermissionInfo)this; - @this.UserId = Null.SetNullInteger(dr["UserID"]); - @this.Username = Null.SetNullString(dr["Username"]); - @this.DisplayName = Null.SetNullString(dr["DisplayName"]); - if (@this.UserId == Null.NullInteger) + this.userId = Null.SetNullInteger(dr["UserID"]); + this.username = Null.SetNullString(dr["Username"]); + this.displayName = Null.SetNullString(dr["DisplayName"]); + if (this.userId == Null.NullInteger) { - @this.RoleId = Null.SetNullInteger(dr["RoleID"]); - @this.RoleName = Null.SetNullString(dr["RoleName"]); + this.roleId = Null.SetNullInteger(dr["RoleID"]); + this.roleName = Null.SetNullString(dr["RoleName"]); } else { - @this.RoleId = int.Parse(Globals.glbRoleNothing); - @this.RoleName = string.Empty; + this.roleId = int.Parse(Globals.glbRoleNothing); + this.roleName = string.Empty; } - @this.AllowAccess = Null.SetNullBoolean(dr["AllowAccess"]); + this.allowAccess = Null.SetNullBoolean(dr["AllowAccess"]); } } } diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Core/DotNetNuke.Tests.Core.csproj b/DNN Platform/Tests/DotNetNuke.Tests.Core/DotNetNuke.Tests.Core.csproj index eef43699581..5e034e1ac88 100644 --- a/DNN Platform/Tests/DotNetNuke.Tests.Core/DotNetNuke.Tests.Core.csproj +++ b/DNN Platform/Tests/DotNetNuke.Tests.Core/DotNetNuke.Tests.Core.csproj @@ -209,6 +209,8 @@ + + diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Core/Security/Permissions/PermissionInfoBaseTests.cs b/DNN Platform/Tests/DotNetNuke.Tests.Core/Security/Permissions/PermissionInfoBaseTests.cs new file mode 100644 index 00000000000..116bf2d011e --- /dev/null +++ b/DNN Platform/Tests/DotNetNuke.Tests.Core/Security/Permissions/PermissionInfoBaseTests.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information + +namespace DotNetNuke.Tests.Core.Security.Permissions +{ + using DotNetNuke.Common.Utilities; + using DotNetNuke.Security.Permissions; + using NUnit.Framework; + + [TestFixture] + public class PermissionInfoBaseTests + { + [Test] + public void SerializesXMLProperly() + { + // Arrange + var derived = new DerivedPermissionInfo + { + AllowAccess = true, + DisplayName = "Test Name", + RoleID = 123, + RoleName = "Test Role", + UserID = 234, + Username = "Test User", + }; + + // Act + var xml = XmlUtils.Serialize(derived); + + // Assert + Assert.IsNotNull(xml); + Assert.True(xml.Contains("allowaccess")); + Assert.True(xml.Contains("displayname")); + Assert.True(xml.Contains("roleid")); + Assert.True(xml.Contains("rolename")); + Assert.True(xml.Contains("userid")); + Assert.True(xml.Contains("username")); + } + } + + public class DerivedPermissionInfo : PermissionInfoBase + { + } +} diff --git a/DNN Platform/Tests/DotNetNuke.Tests.Core/Security/Permissions/PermissionInfoTests.cs b/DNN Platform/Tests/DotNetNuke.Tests.Core/Security/Permissions/PermissionInfoTests.cs new file mode 100644 index 00000000000..3b6898bbb68 --- /dev/null +++ b/DNN Platform/Tests/DotNetNuke.Tests.Core/Security/Permissions/PermissionInfoTests.cs @@ -0,0 +1,108 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information + +namespace DotNetNuke.Tests.Core.Security.Permissions +{ + using System; + using System.IO; + using System.Text; + + using DotNetNuke.Abstractions.Security.Permissions; + using DotNetNuke.Common.Utilities; + using DotNetNuke.Security.Permissions; + using NUnit.Framework; + + [TestFixture] + public class PermissionInfoTests + { + [Test] + public void SerializesJson_IncluddingObsoleteProperties() + { + // Arrange + var permissionInfo = new PermissionInfo + { + ModuleDefID = 123, + PermissionCode = "test", + PermissionID = 456, + PermissionKey = "testKey", + PermissionName = "testName", + }; + + // Act + var json = Json.Serialize(permissionInfo); + + // Assert + Assert.NotNull(json); + Assert.False(json.Contains(nameof(permissionInfo.ModuleDefId))); + Assert.True(json.Contains(nameof(permissionInfo.PermissionCode))); + Assert.True(json.Contains(nameof(permissionInfo.PermissionID))); // old obsolete casing. + Assert.True(json.Contains(nameof(permissionInfo.PermissionId))); // new casing. + Assert.True(json.Contains(nameof(permissionInfo.PermissionKey))); + Assert.False(json.Contains(nameof(permissionInfo.PermissionName))); + } + + [Test] + public void DeserializesJson_Properly() + { + // Arrange + var json = "{\"PermissionCode\":\"test\",\"PermissionID\":456,\"PermissionKey\":\"testKey\"}"; + + // Act + var permissionInfo = Json.Deserialize(json); + + // Assert + Assert.NotNull(permissionInfo); + Assert.AreEqual("test", permissionInfo.PermissionCode); + Assert.AreEqual(456, permissionInfo.PermissionID); + Assert.AreEqual(456, ((IPermissionDefinitionInfo)permissionInfo).PermissionId); + Assert.AreEqual("testKey", permissionInfo.PermissionKey); + } + + [Test] + public void SerializesXml_IncludesObsoleteProperties() + { + // Arrange + var permissionInfo = new PermissionInfo + { + ModuleDefID = 123, + PermissionCode = "test", + PermissionID = 456, + PermissionKey = "testKey", + PermissionName = "testName", + }; + // Act + var xml = XmlUtils.Serialize(permissionInfo); + + // Assert + Assert.NotNull(xml); + Assert.False(xml.IndexOf("moduledefid", StringComparison.OrdinalIgnoreCase) >= 0); + Assert.True(xml.Contains("permissioncode")); + Assert.True(xml.Contains("permissionid")); + Assert.True(xml.Contains("permissionkey")); + Assert.False(xml.IndexOf("permissionname", StringComparison.OrdinalIgnoreCase) >= 0); + } + + [Test] + public void Deserializes_Properly() + { + // Arrange + var xml = "test456testKey"; + var stream = new MemoryStream(); + var writer = new StreamWriter(stream, Encoding.UTF8); + writer.Write(xml); + writer.Flush(); + stream.Position = 0; + + // Act + var permissionInfo = (PermissionInfo)XmlUtils.Deserialize(stream, typeof(PermissionInfo)); + + // Assert + Assert.NotNull(permissionInfo); + Assert.AreEqual("test", permissionInfo.PermissionCode); + Assert.AreEqual(456, permissionInfo.PermissionID); + Assert.AreEqual(456, ((IPermissionDefinitionInfo)permissionInfo).PermissionId); + Assert.AreEqual("testKey", permissionInfo.PermissionKey); + } + } +}