From 9da3c0a1d690d35ef7635eabd715202eeec98aaf Mon Sep 17 00:00:00 2001 From: Kelly Adams Date: Mon, 18 Sep 2017 17:07:25 -0700 Subject: [PATCH 1/2] Converted to VS2017 csproj. Added test project. Added extension methods on ClaimsPrincipal. --- .../ClaimsPrincipalGetUserIdTests.cs | 18 +++++++ .../IntelliTect.Utilities.Tests.csproj | 22 ++++++++ .../IntelliTect.Utilities.csproj | 50 +++---------------- .../Properties/AssemblyInfo.cs | 33 +----------- .../Security/ClaimsPrincipalExtensions.cs | 39 +++++++++++++++ IntelliTect.sln | 21 +++++--- README.md | 6 ++- 7 files changed, 108 insertions(+), 81 deletions(-) create mode 100644 IntelliTect.Utilities.Tests/ClaimsPrincipalGetUserIdTests.cs create mode 100644 IntelliTect.Utilities.Tests/IntelliTect.Utilities.Tests.csproj create mode 100644 IntelliTect.Utilities/Security/ClaimsPrincipalExtensions.cs diff --git a/IntelliTect.Utilities.Tests/ClaimsPrincipalGetUserIdTests.cs b/IntelliTect.Utilities.Tests/ClaimsPrincipalGetUserIdTests.cs new file mode 100644 index 0000000..046c459 --- /dev/null +++ b/IntelliTect.Utilities.Tests/ClaimsPrincipalGetUserIdTests.cs @@ -0,0 +1,18 @@ +using System; +using System.Security.Claims; +using IntelliTect.Utilities.Security; +using Xunit; + +namespace IntelliTect.Utilities.Tests +{ + public class ClaimsPrincipalGetUserIdTests + { + [Fact] + public void WhenClaimsPrincipalNull_Should_Throw() + { + ClaimsPrincipal sut = null; + + Assert.Throws(() => sut.GetUserId()); + } + } +} \ No newline at end of file diff --git a/IntelliTect.Utilities.Tests/IntelliTect.Utilities.Tests.csproj b/IntelliTect.Utilities.Tests/IntelliTect.Utilities.Tests.csproj new file mode 100644 index 0000000..dfc8d3f --- /dev/null +++ b/IntelliTect.Utilities.Tests/IntelliTect.Utilities.Tests.csproj @@ -0,0 +1,22 @@ + + + + net462 + + false + + + + + + + + + + + + + + + + diff --git a/IntelliTect.Utilities/IntelliTect.Utilities.csproj b/IntelliTect.Utilities/IntelliTect.Utilities.csproj index fe9de74..9834486 100644 --- a/IntelliTect.Utilities/IntelliTect.Utilities.csproj +++ b/IntelliTect.Utilities/IntelliTect.Utilities.csproj @@ -1,56 +1,22 @@ - - - + - Debug - AnyCPU - {6E9F4A6A-F611-4ECB-8AAC-B2079C0B9DF5} - Library - Properties IntelliTect.Utilities - IntelliTect.Utilities - v4.6.2 - 512 - + net462 + A utility library for IntelliTect + IntelliTect + IntelliTect + Copyright © IntelliTect 2017 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 ..\SolutionRuleset.ruleset true + full + true - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/IntelliTect.Utilities/Properties/AssemblyInfo.cs b/IntelliTect.Utilities/Properties/AssemblyInfo.cs index 9892e3d..13f5ae5 100644 --- a/IntelliTect.Utilities/Properties/AssemblyInfo.cs +++ b/IntelliTect.Utilities/Properties/AssemblyInfo.cs @@ -1,38 +1,7 @@ using System; -using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("IntelliTect.Utilities")] -[assembly: AssemblyDescription("A utility library for IntelliTect")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("IntelliTect")] -[assembly: AssemblyProduct("IntelliTect.Utilities")] -[assembly: AssemblyCopyright("Copyright © IntelliTect 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: CLSCompliant(true)] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. +[assembly: CLSCompliant(true)] [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("6e9f4a6a-f611-4ecb-8aac-b2079c0b9df5")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/IntelliTect.Utilities/Security/ClaimsPrincipalExtensions.cs b/IntelliTect.Utilities/Security/ClaimsPrincipalExtensions.cs new file mode 100644 index 0000000..ada97cd --- /dev/null +++ b/IntelliTect.Utilities/Security/ClaimsPrincipalExtensions.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; + +namespace IntelliTect.Utilities.Security +{ + public static class ClaimsPrincipalExtensions + { + /// + /// Gets the user ID from a . + /// + /// The to find a user ID for. + /// A , or null if the doesn't contain a . + /// principal is null. + public static string GetUserId(this ClaimsPrincipal principal) + { + if (principal == null) throw new ArgumentNullException(nameof(principal)); + + Claim claim = principal.FindFirst(ClaimTypes.NameIdentifier); + return claim?.Value; + } + + + /// + /// Gets all the roles a belongs to. + /// + /// The to find roles for. + /// An of if found, or an empty set. + /// principal is null. + public static IEnumerable GetRoles(this ClaimsPrincipal principal) + { + if (principal == null) throw new ArgumentNullException(nameof(principal)); + + IEnumerable claims = principal.FindAll(ClaimTypes.Role); + return claims?.Select(claim => claim.Value) ?? Enumerable.Empty(); + } + } +} \ No newline at end of file diff --git a/IntelliTect.sln b/IntelliTect.sln index 564322a..1b6ee60 100644 --- a/IntelliTect.sln +++ b/IntelliTect.sln @@ -1,9 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26206.0 +VisualStudioVersion = 15.0.26730.15 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntelliTect.Utilities", "IntelliTect.Utilities\IntelliTect.Utilities.csproj", "{6E9F4A6A-F611-4ECB-8AAC-B2079C0B9DF5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntelliTect.Utilities", "IntelliTect.Utilities\IntelliTect.Utilities.csproj", "{4AEDF7B5-8FD1-4361-B230-173646A0D20C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntelliTect.Utilities.Tests", "IntelliTect.Utilities.Tests\IntelliTect.Utilities.Tests.csproj", "{B0281AA3-FAED-4A2C-8C5A-C2F3DC39511A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,12 +13,19 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6E9F4A6A-F611-4ECB-8AAC-B2079C0B9DF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E9F4A6A-F611-4ECB-8AAC-B2079C0B9DF5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E9F4A6A-F611-4ECB-8AAC-B2079C0B9DF5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E9F4A6A-F611-4ECB-8AAC-B2079C0B9DF5}.Release|Any CPU.Build.0 = Release|Any CPU + {4AEDF7B5-8FD1-4361-B230-173646A0D20C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4AEDF7B5-8FD1-4361-B230-173646A0D20C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4AEDF7B5-8FD1-4361-B230-173646A0D20C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4AEDF7B5-8FD1-4361-B230-173646A0D20C}.Release|Any CPU.Build.0 = Release|Any CPU + {B0281AA3-FAED-4A2C-8C5A-C2F3DC39511A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0281AA3-FAED-4A2C-8C5A-C2F3DC39511A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0281AA3-FAED-4A2C-8C5A-C2F3DC39511A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0281AA3-FAED-4A2C-8C5A-C2F3DC39511A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DE282392-8D28-4F0B-8A80-449A5781097B} + EndGlobalSection EndGlobal diff --git a/README.md b/README.md index d88e1b1..b2f9d85 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,13 @@ Libraries of useful C# things, focused on shipping Nuget packages. Libraries ========= +### IntelliTect.Utilities: [![NuGet](https://img.shields.io/nuget/v/IntelliTect.Utilities.svg)](https://www.nuget.org/packages/IntelliTect.Utilities/) -* IntelliTect.Utilities [![NuGet](https://img.shields.io/nuget/v/IntelliTect.Utilities.svg)](https://www.nuget.org/packages/IntelliTect.Utilities/) +### Namespaces within this library: +* IntelliTect.Utilities - AssemblyInfo: Gets an assembly's linker date/time. +* IntelliTect.Utilities.Security + - ClaimsPrincipalExtensions: Extention methods to get a user ID and roles. Contributing ============ From 52f506d934e425a2e3ecd204b8b7623a2084eb2f Mon Sep 17 00:00:00 2001 From: Kelly Adams Date: Mon, 18 Sep 2017 17:53:57 -0700 Subject: [PATCH 2/2] Fleshed out tests. Added fall-through to get Name claim if Id not found. --- .../ClaimsPrincipalGetRolesTests.cs | 35 +++++++++++++++++++ .../ClaimsPrincipalGetUserIdTests.cs | 17 +++++++++ .../IntelliTect.Utilities.Tests.csproj | 2 +- .../IntelliTect.Utilities.nuspec | 2 +- .../Security/ClaimsPrincipalExtensions.cs | 2 ++ 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 IntelliTect.Utilities.Tests/ClaimsPrincipalGetRolesTests.cs diff --git a/IntelliTect.Utilities.Tests/ClaimsPrincipalGetRolesTests.cs b/IntelliTect.Utilities.Tests/ClaimsPrincipalGetRolesTests.cs new file mode 100644 index 0000000..eeea264 --- /dev/null +++ b/IntelliTect.Utilities.Tests/ClaimsPrincipalGetRolesTests.cs @@ -0,0 +1,35 @@ +using System; +using System.Security.Claims; +using System.Security.Principal; +using IntelliTect.Utilities.Security; +using Xunit; + +namespace IntelliTect.Utilities.Tests +{ + public class ClaimsPrincipalGetRolesTests + { + [Fact] + public void WhenClaimsPrincipalNull_Should_Throw() + { + ClaimsPrincipal sut = null; + + Assert.Throws(() => sut.GetRoles()); + } + + [Fact] + public void WhenClaimsPrincipalHasNoRoles_Should_ReturnEmpty() + { + ClaimsPrincipal sut = new ClaimsPrincipal(); + + Assert.Empty(sut.GetRoles()); + } + + [Fact] + public void WhenClaimsPrincipalHasRoles_Should_ReturnNotEmpty() + { + ClaimsPrincipal sut = new GenericPrincipal(new GenericIdentity("Uncle Festus"), new[] {"Foo", "Bar"}); + + Assert.Collection(sut.GetRoles(), s => Assert.Equal("Foo", s), t => Assert.Equal("Bar", t) ); + } + } +} \ No newline at end of file diff --git a/IntelliTect.Utilities.Tests/ClaimsPrincipalGetUserIdTests.cs b/IntelliTect.Utilities.Tests/ClaimsPrincipalGetUserIdTests.cs index 046c459..814c58d 100644 --- a/IntelliTect.Utilities.Tests/ClaimsPrincipalGetUserIdTests.cs +++ b/IntelliTect.Utilities.Tests/ClaimsPrincipalGetUserIdTests.cs @@ -1,5 +1,6 @@ using System; using System.Security.Claims; +using System.Security.Principal; using IntelliTect.Utilities.Security; using Xunit; @@ -14,5 +15,21 @@ public void WhenClaimsPrincipalNull_Should_Throw() Assert.Throws(() => sut.GetUserId()); } + + [Fact] + public void WhenClaimsPrincipalHasNoProperty_Should_ReturnNull() + { + ClaimsPrincipal sut = new ClaimsPrincipal(); + + Assert.Null(sut.GetUserId()); + } + + [Fact] + public void WhenClaimsPrincipalHasId_Should_ReturnString() + { + ClaimsPrincipal sut = new GenericPrincipal(new GenericIdentity("Taki The Frog"), new []{ "Bar" } ); + + Assert.Equal("Taki The Frog", sut.GetUserId()); + } } } \ No newline at end of file diff --git a/IntelliTect.Utilities.Tests/IntelliTect.Utilities.Tests.csproj b/IntelliTect.Utilities.Tests/IntelliTect.Utilities.Tests.csproj index dfc8d3f..dc20886 100644 --- a/IntelliTect.Utilities.Tests/IntelliTect.Utilities.Tests.csproj +++ b/IntelliTect.Utilities.Tests/IntelliTect.Utilities.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/IntelliTect.Utilities/IntelliTect.Utilities.nuspec b/IntelliTect.Utilities/IntelliTect.Utilities.nuspec index e622049..3d8374d 100644 --- a/IntelliTect.Utilities/IntelliTect.Utilities.nuspec +++ b/IntelliTect.Utilities/IntelliTect.Utilities.nuspec @@ -10,7 +10,7 @@ https://github.com/IntelliTect/IntelliTect true $description$ - Added assembly linker date. + Added ClaimsPrincipal extensions. Copyright 2017 IntelliTect diff --git a/IntelliTect.Utilities/Security/ClaimsPrincipalExtensions.cs b/IntelliTect.Utilities/Security/ClaimsPrincipalExtensions.cs index ada97cd..c17b502 100644 --- a/IntelliTect.Utilities/Security/ClaimsPrincipalExtensions.cs +++ b/IntelliTect.Utilities/Security/ClaimsPrincipalExtensions.cs @@ -18,6 +18,8 @@ public static string GetUserId(this ClaimsPrincipal principal) if (principal == null) throw new ArgumentNullException(nameof(principal)); Claim claim = principal.FindFirst(ClaimTypes.NameIdentifier); + if (claim != null) return claim.Value; + claim = principal.FindFirst(ClaimTypes.Name); return claim?.Value; }