diff --git a/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/RoleSecuredTypes.cs b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/RoleSecuredTypes.cs new file mode 100644 index 000000000..a48ad4770 --- /dev/null +++ b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/RoleSecuredTypes.cs @@ -0,0 +1,29 @@ +// Copyright (c) Cratis. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Cratis.Arc.Authorization; + +namespace Cratis.Arc.ProxyGenerator.ControllerBased.for_MethodInfoExtensions; + +/// +/// Holds the shapes roles can be declared in, for reading them back. +/// +/// +/// Both Cratis.Arc.Authorization and Microsoft.AspNetCore.Authorization declare an +/// Authorize attribute, so the ASP.NET Core one is written out in full where the named-argument form is needed. +/// +public class RoleSecuredTypes +{ + [Roles("Librarian")] + public void SingleRoleFromConstructor() { } + + [Roles("Librarian", "Admin")] + public void MultipleRolesFromConstructor() { } + + [Microsoft.AspNetCore.Authorization.Authorize(Roles = "Librarian")] + public void RoleFromNamedArgument() { } + + [Roles("Librarian")] + [Microsoft.AspNetCore.Authorization.Authorize(Roles = "Librarian")] + public void RoleFromBothForms() { } +} diff --git a/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_both_forms_combined.cs b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_both_forms_combined.cs new file mode 100644 index 000000000..46d7b4b47 --- /dev/null +++ b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_both_forms_combined.cs @@ -0,0 +1,18 @@ +// Copyright (c) Cratis. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; + +namespace Cratis.Arc.ProxyGenerator.ControllerBased.for_MethodInfoExtensions.when_extracting_roles; + +public class from_both_forms_combined : Specification +{ + MethodInfo _method; + IEnumerable _result; + + void Establish() => _method = typeof(RoleSecuredTypes).GetMethod(nameof(RoleSecuredTypes.RoleFromBothForms)); + + void Because() => _result = _method.GetRoles(); + + [Fact] void should_deduplicate_the_roles() => _result.ShouldContainOnly(["Librarian"]); +} diff --git a/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_constructor_form_with_multiple_roles.cs b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_constructor_form_with_multiple_roles.cs new file mode 100644 index 000000000..a539b2c75 --- /dev/null +++ b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_constructor_form_with_multiple_roles.cs @@ -0,0 +1,18 @@ +// Copyright (c) Cratis. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; + +namespace Cratis.Arc.ProxyGenerator.ControllerBased.for_MethodInfoExtensions.when_extracting_roles; + +public class from_constructor_form_with_multiple_roles : Specification +{ + MethodInfo _method; + IEnumerable _result; + + void Establish() => _method = typeof(RoleSecuredTypes).GetMethod(nameof(RoleSecuredTypes.MultipleRolesFromConstructor)); + + void Because() => _result = _method.GetRoles(); + + [Fact] void should_yield_all_roles() => _result.ShouldContainOnly(["Librarian", "Admin"]); +} diff --git a/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_constructor_form_with_single_role.cs b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_constructor_form_with_single_role.cs new file mode 100644 index 000000000..fcfaf30df --- /dev/null +++ b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_constructor_form_with_single_role.cs @@ -0,0 +1,18 @@ +// Copyright (c) Cratis. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; + +namespace Cratis.Arc.ProxyGenerator.ControllerBased.for_MethodInfoExtensions.when_extracting_roles; + +public class from_constructor_form_with_single_role : Specification +{ + MethodInfo _method; + IEnumerable _result; + + void Establish() => _method = typeof(RoleSecuredTypes).GetMethod(nameof(RoleSecuredTypes.SingleRoleFromConstructor)); + + void Because() => _result = _method.GetRoles(); + + [Fact] void should_yield_the_role() => _result.ShouldContainOnly(["Librarian"]); +} diff --git a/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_named_argument_form.cs b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_named_argument_form.cs new file mode 100644 index 000000000..0649e53bd --- /dev/null +++ b/Source/DotNET/Tools/ProxyGenerator.Specs/ControllerBased/for_MethodInfoExtensions/when_extracting_roles/from_named_argument_form.cs @@ -0,0 +1,18 @@ +// Copyright (c) Cratis. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; + +namespace Cratis.Arc.ProxyGenerator.ControllerBased.for_MethodInfoExtensions.when_extracting_roles; + +public class from_named_argument_form : Specification +{ + MethodInfo _method; + IEnumerable _result; + + void Establish() => _method = typeof(RoleSecuredTypes).GetMethod(nameof(RoleSecuredTypes.RoleFromNamedArgument)); + + void Because() => _result = _method.GetRoles(); + + [Fact] void should_yield_the_role() => _result.ShouldContainOnly(["Librarian"]); +} diff --git a/Source/DotNET/Tools/ProxyGenerator/MethodInfoExtensions.cs b/Source/DotNET/Tools/ProxyGenerator/MethodInfoExtensions.cs index b624143c4..a46588e50 100644 --- a/Source/DotNET/Tools/ProxyGenerator/MethodInfoExtensions.cs +++ b/Source/DotNET/Tools/ProxyGenerator/MethodInfoExtensions.cs @@ -105,6 +105,7 @@ static IEnumerable GetRolesFromAttributesData(IEnumerable a.MemberName == "Roles"); if (rolesArg != default && rolesArg.TypedValue.Value is string rolesStr && !string.IsNullOrEmpty(rolesStr)) { @@ -113,6 +114,16 @@ static IEnumerable GetRolesFromAttributesData(IEnumerable 0 && + attr.ConstructorArguments[0].Value is IReadOnlyCollection roleArgs) + { + foreach (var role in roleArgs.Select(a => a.Value as string).Where(r => !string.IsNullOrEmpty(r))) + { + yield return role!; + } + } } }