diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.abppkg.analyze.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.abppkg.analyze.json index 096202cd42..c1f39e1aee 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.abppkg.analyze.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.abppkg.analyze.json @@ -11,9 +11,9 @@ "name": "AbpIdentityServerDomainSharedModule" }, { - "declaringAssemblyName": "Volo.Abp.AutoMapper", - "namespace": "Volo.Abp.AutoMapper", - "name": "AbpAutoMapperModule" + "declaringAssemblyName": "Volo.Abp.Mapperly", + "namespace": "Volo.Abp.Mapperly", + "name": "AbpMapperlyModule" }, { "declaringAssemblyName": "Volo.Abp.Identity.Domain", diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj index fd856b4ca3..fb9248b9cb 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj @@ -17,7 +17,7 @@ - + diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs index 9b9dde5c96..1fedb1cc74 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs @@ -5,7 +5,7 @@ using IdentityServer4.Stores; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; -using Volo.Abp.AutoMapper; +using Volo.Abp.Mapperly; using Volo.Abp.BackgroundWorkers; using Volo.Abp.Caching; using Volo.Abp.Domain.Entities.Events.Distributed; @@ -28,7 +28,7 @@ namespace Volo.Abp.IdentityServer; [DependsOn( typeof(AbpIdentityServerDomainSharedModule), - typeof(AbpAutoMapperModule), + typeof(AbpMapperlyModule), typeof(AbpIdentityDomainModule), typeof(AbpSecurityModule), typeof(AbpCachingModule), @@ -41,12 +41,7 @@ public class AbpIdentityServerDomainModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddAutoMapperObjectMapper(); - - Configure(options => - { - options.AddProfile(validate: true); - }); + context.Services.AddMapperlyObjectMapper(); Configure(options => { diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AllowedSigningAlgorithmsConverter.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AllowedSigningAlgorithmsConverter.cs index 25bd38ad10..49297a3d21 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AllowedSigningAlgorithmsConverter.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AllowedSigningAlgorithmsConverter.cs @@ -1,36 +1,24 @@ using System; -using System.Collections.Generic; using System.Linq; -using AutoMapper; namespace Volo.Abp.IdentityServer; -public class AllowedSigningAlgorithmsConverter : - IValueConverter, string>, - IValueConverter> +public static class AllowedSigningAlgorithmsConverter { - public static AllowedSigningAlgorithmsConverter Converter = new AllowedSigningAlgorithmsConverter(); - - public string Convert(ICollection sourceMember, ResolutionContext context) - { - if (sourceMember == null || !sourceMember.Any()) - { - return null; - } - return sourceMember.Aggregate((x, y) => $"{x},{y}"); - } - - public ICollection Convert(string sourceMember, ResolutionContext context) + private const char Separator = ','; + + public static string[] SplitToArray(string algorithms) { - var list = new HashSet(); - if (!String.IsNullOrWhiteSpace(sourceMember)) + if (string.IsNullOrWhiteSpace(algorithms)) { - sourceMember = sourceMember.Trim(); - foreach (var item in sourceMember.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Distinct()) - { - list.Add(item); - } + return []; } - return list; + + return algorithms + .Split([Separator], StringSplitOptions.RemoveEmptyEntries) + .Select(x => x.Trim()) + .Where(x => !string.IsNullOrEmpty(x)) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray(); } -} +} \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs deleted file mode 100644 index 53a7de989c..0000000000 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerAutoMapperProfile.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System.Collections.Generic; -using System.Security.Claims; -using AutoMapper; -using Volo.Abp.IdentityServer.ApiResources; -using Volo.Abp.IdentityServer.ApiScopes; -using Volo.Abp.IdentityServer.Clients; -using Volo.Abp.IdentityServer.Devices; -using Volo.Abp.IdentityServer.Grants; -using Volo.Abp.IdentityServer.IdentityResources; - -namespace Volo.Abp.IdentityServer; - -public class IdentityServerAutoMapperProfile : Profile -{ - /// - /// TODO: Reverse maps will not used probably. Remove those will not used - /// - public IdentityServerAutoMapperProfile() - { - CreateMap() - .ConstructUsing(src => src.Type) - .ReverseMap() - .ForMember(dest => dest.Type, opt => opt.MapFrom(src => src)); - - CreateClientMap(); - CreateApiResourceMap(); - CreateApiScopeMap(); - CreateIdentityResourceMap(); - CreatePersistedGrantMap(); - CreateDeviceFlowCodesMap(); - } - - private void CreateClientMap() - { - CreateMap() - .ConstructUsing(src => src.Origin) - .ReverseMap() - .ForMember(dest => dest.Origin, opt => opt.MapFrom(src => src)); - - CreateMap>() - .ReverseMap(); - - CreateMap() - .ForMember(dest => dest.ProtocolType, opt => opt.Condition(srs => srs != null)) - .ForMember(x => x.AllowedIdentityTokenSigningAlgorithms, opts => opts.ConvertUsing(AllowedSigningAlgorithmsConverter.Converter, x => x.AllowedIdentityTokenSigningAlgorithms)) - .ReverseMap() - .ForMember(x => x.AllowedIdentityTokenSigningAlgorithms, opts => opts.ConvertUsing(AllowedSigningAlgorithmsConverter.Converter, x => x.AllowedIdentityTokenSigningAlgorithms)); - - CreateMap() - .ConstructUsing(src => src.Origin) - .ReverseMap() - .ForMember(dest => dest.Origin, opt => opt.MapFrom(src => src)); - - CreateMap() - .ConstructUsing(src => src.Provider) - .ReverseMap() - .ForMember(dest => dest.Provider, opt => opt.MapFrom(src => src)); - - CreateMap(MemberList.None) - .ConstructUsing(src => new Claim(src.Type, src.Value)) - .ReverseMap(); - - CreateMap(MemberList.None) - .ConstructUsing(src => new IdentityServer4.Models.ClientClaim(src.Type, src.Value, ClaimValueTypes.String)) - .ReverseMap(); - - CreateMap() - .ConstructUsing(src => src.Scope) - .ReverseMap() - .ForMember(dest => dest.Scope, opt => opt.MapFrom(src => src)); - - CreateMap() - .ConstructUsing(src => src.PostLogoutRedirectUri) - .ReverseMap() - .ForMember(dest => dest.PostLogoutRedirectUri, opt => opt.MapFrom(src => src)); - - CreateMap() - .ConstructUsing(src => src.RedirectUri) - .ReverseMap() - .ForMember(dest => dest.RedirectUri, opt => opt.MapFrom(src => src)); - - CreateMap() - .ConstructUsing(src => src.GrantType) - .ReverseMap() - .ForMember(dest => dest.GrantType, opt => opt.MapFrom(src => src)); - - CreateMap(MemberList.Destination) - .ForMember(dest => dest.Type, opt => opt.Condition(srs => srs != null)) - .ReverseMap(); - - CreateMap(); - } - - private void CreateApiResourceMap() - { - CreateMap() - .ForMember(dest => dest.ApiSecrets, opt => opt.MapFrom(src => src.Secrets)) - .ForMember(x => x.AllowedAccessTokenSigningAlgorithms, opts => opts.ConvertUsing(AllowedSigningAlgorithmsConverter.Converter, x => x.AllowedAccessTokenSigningAlgorithms)); - - CreateMap(); - - CreateMap() - .ConstructUsing(x => x.Scope) - .ReverseMap() - .ForMember(dest => dest.Scope, opt => opt.MapFrom(src => src)); - - CreateMap>() - .ReverseMap(); - - CreateMap(); - } - - private void CreateApiScopeMap() - { - CreateMap>() - .ReverseMap(); - - CreateMap() - .ConstructUsing(x => x.Type) - .ReverseMap() - .ForMember(dest => dest.Type, opt => opt.MapFrom(src => src)); - - CreateMap(MemberList.Destination) - .ConstructUsing(src => new IdentityServer4.Models.ApiScope()) - .ReverseMap(); - } - - private void CreateIdentityResourceMap() - { - CreateMap() - .ConstructUsing(src => new IdentityServer4.Models.IdentityResource()); - - CreateMap() - .ConstructUsing(x => x.Type) - .ReverseMap() - .ForMember(dest => dest.Type, opt => opt.MapFrom(src => src)); - - CreateMap>() - .ReverseMap(); - - CreateMap(); - } - - private void CreatePersistedGrantMap() - { - //TODO: Why PersistedGrant mapping is in this profile? - CreateMap().ReverseMap(); - CreateMap(); - } - - private void CreateDeviceFlowCodesMap() - { - CreateMap(); - } -} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerMapperlyMappers.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerMapperlyMappers.cs new file mode 100644 index 0000000000..dbeee6d7f1 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityServerMapperlyMappers.cs @@ -0,0 +1,238 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using Riok.Mapperly.Abstractions; +using Volo.Abp.Mapperly; +using Volo.Abp.IdentityServer.ApiResources; +using Volo.Abp.IdentityServer.ApiScopes; +using Volo.Abp.IdentityServer.Clients; +using Volo.Abp.IdentityServer.Devices; +using Volo.Abp.IdentityServer.Grants; +using Volo.Abp.IdentityServer.IdentityResources; + +namespace Volo.Abp.IdentityServer; + +[Mapper] +public partial class ClientToISClientMapper : MapperBase +{ + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.AllowedIdentityTokenSigningAlgorithms))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.Claims))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.ClientSecrets))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.AllowedGrantTypes))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.AllowedScopes))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.AllowedCorsOrigins))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.RedirectUris))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.PostLogoutRedirectUris))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.IdentityProviderRestrictions))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.Properties))] + public override partial IdentityServer4.Models.Client Map(Client source); + + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.AllowedIdentityTokenSigningAlgorithms))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.Claims))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.ClientSecrets))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.AllowedGrantTypes))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.AllowedScopes))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.AllowedCorsOrigins))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.RedirectUris))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.PostLogoutRedirectUris))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.IdentityProviderRestrictions))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.Client.Properties))] + public override partial void Map(Client source, IdentityServer4.Models.Client destination); + + public override void AfterMap(Client source, IdentityServer4.Models.Client destination) + { + destination.AllowedIdentityTokenSigningAlgorithms = AllowedSigningAlgorithmsConverter.SplitToArray(source.AllowedIdentityTokenSigningAlgorithms); + if (source.Properties != null) + { + destination.Properties = source.Properties.ToDictionary(x => x.Key, x => x.Value); + } + if (source.Claims != null) + { + destination.Claims = source.Claims.Select(x => new IdentityServer4.Models.ClientClaim(x.Type, x.Value, ClaimValueTypes.String)).ToList(); + } + if (source.ClientSecrets != null) + { + destination.ClientSecrets = source.ClientSecrets.Select(x => new IdentityServer4.Models.Secret(x.Value, x.Expiration) { Type = x.Type, Description = x.Description }).ToList(); + } + if (source.AllowedGrantTypes != null) + { + destination.AllowedGrantTypes = source.AllowedGrantTypes.Select(x => x.GrantType).ToList(); + } + if (source.AllowedScopes != null) + { + destination.AllowedScopes = source.AllowedScopes.Select(x => x.Scope).ToList(); + } + if (source.AllowedCorsOrigins != null) + { + destination.AllowedCorsOrigins = source.AllowedCorsOrigins.Select(x => x.Origin).ToList(); + } + if (source.RedirectUris != null) + { + destination.RedirectUris = source.RedirectUris.Select(x => x.RedirectUri).ToList(); + } + if (source.PostLogoutRedirectUris != null) + { + destination.PostLogoutRedirectUris = source.PostLogoutRedirectUris.Select(x => x.PostLogoutRedirectUri).ToList(); + } + if (source.IdentityProviderRestrictions != null) + { + destination.IdentityProviderRestrictions = source.IdentityProviderRestrictions.Select(x => x.Provider).ToList(); + } + } +} + +[Mapper] +public partial class ApiResourceToISApiResourceMapper : MapperBase +{ + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.AllowedAccessTokenSigningAlgorithms))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.ApiSecrets))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.Properties))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.Scopes))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.UserClaims))] + public override partial IdentityServer4.Models.ApiResource Map(ApiResource source); + + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.AllowedAccessTokenSigningAlgorithms))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.ApiSecrets))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.Properties))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.Scopes))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiResource.UserClaims))] + public override partial void Map(ApiResource source, IdentityServer4.Models.ApiResource destination); + + public override void AfterMap(ApiResource source, IdentityServer4.Models.ApiResource destination) + { + destination.AllowedAccessTokenSigningAlgorithms = AllowedSigningAlgorithmsConverter.SplitToArray(source.AllowedAccessTokenSigningAlgorithms); + if (source.Properties != null) + { + destination.Properties = source.Properties.ToDictionary(x => x.Key, x => x.Value); + } + if (source.Secrets != null) + { + destination.ApiSecrets = source.Secrets.Select(x => new IdentityServer4.Models.Secret(x.Value, x.Expiration) { Type = x.Type, Description = x.Description }).ToList(); + } + if (source.UserClaims != null) + { + destination.UserClaims = source.UserClaims.Select(x => x.Type).ToList(); + } + if (source.Scopes != null) + { + destination.Scopes = source.Scopes.Select(x => x.Scope).ToList(); + } + } +} + +[Mapper] +public partial class ApiScopeToISApiScopeMapper : MapperBase +{ + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiScope.UserClaims))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiScope.Properties))] + public override partial IdentityServer4.Models.ApiScope Map(ApiScope source); + + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiScope.UserClaims))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.ApiScope.Properties))] + public override partial void Map(ApiScope source, IdentityServer4.Models.ApiScope destination); + + public override void AfterMap(ApiScope source, IdentityServer4.Models.ApiScope destination) + { + if (source.Properties != null) + { + destination.Properties = source.Properties.ToDictionary(x => x.Key, x => x.Value); + } + if (source.UserClaims != null) + { + destination.UserClaims = source.UserClaims.Select(x => x.Type).ToList(); + } + } +} + +[Mapper] +public partial class IdentityResourceToISIdentityResourceMapper : MapperBase +{ + [MapperIgnoreTarget(nameof(IdentityServer4.Models.IdentityResource.UserClaims))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.IdentityResource.Properties))] + public override partial IdentityServer4.Models.IdentityResource Map(IdentityResource source); + + [MapperIgnoreTarget(nameof(IdentityServer4.Models.IdentityResource.UserClaims))] + [MapperIgnoreTarget(nameof(IdentityServer4.Models.IdentityResource.Properties))] + public override partial void Map(IdentityResource source, IdentityServer4.Models.IdentityResource destination); + + public override void AfterMap(IdentityResource source, IdentityServer4.Models.IdentityResource destination) + { + if (source.Properties != null) + { + destination.Properties = source.Properties.ToDictionary(x => x.Key, x => x.Value); + } + if (source.UserClaims != null) + { + destination.UserClaims = source.UserClaims.Select(x => x.Type).ToList(); + } + } +} + +[Mapper] +public partial class ClientToClientEtoMapper : MapperBase +{ + public override partial ClientEto Map(Client source); + public override partial void Map(Client source, ClientEto destination); +} + +[Mapper] +public partial class IdentityResourceToIdentityResourceEtoMapper : MapperBase +{ + public override partial IdentityResourceEto Map(IdentityResource source); + public override partial void Map(IdentityResource source, IdentityResourceEto destination); +} + +[Mapper] +public partial class PersistedGrantToISPersistedGrantMapper : TwoWayMapperBase +{ + public override partial IdentityServer4.Models.PersistedGrant Map(PersistedGrant source); + public override partial void Map(PersistedGrant source, IdentityServer4.Models.PersistedGrant destination); + + public override PersistedGrant ReverseMap(IdentityServer4.Models.PersistedGrant source) + { + var entity = new PersistedGrant(System.Guid.Empty) + { + Key = source.Key, + Type = source.Type, + SubjectId = source.SubjectId, + SessionId = source.SessionId, + ClientId = source.ClientId, + Description = source.Description, + CreationTime = source.CreationTime, + Expiration = source.Expiration, + ConsumedTime = source.ConsumedTime, + Data = source.Data + }; + return entity; + } + + public override void ReverseMap(IdentityServer4.Models.PersistedGrant source, PersistedGrant destination) + { + destination.Key = source.Key; + destination.Type = source.Type; + destination.SubjectId = source.SubjectId; + destination.SessionId = source.SessionId; + destination.ClientId = source.ClientId; + destination.Description = source.Description; + destination.CreationTime = source.CreationTime; + destination.Expiration = source.Expiration; + destination.ConsumedTime = source.ConsumedTime; + destination.Data = source.Data; + } +} + +[Mapper] +public partial class PersistedGrantToPersistedGrantEtoMapper : MapperBase +{ + public override partial PersistedGrantEto Map(PersistedGrant source); + public override partial void Map(PersistedGrant source, PersistedGrantEto destination); +} + +[Mapper] +public partial class DeviceFlowCodesToDeviceFlowCodesEtoMapper : MapperBase +{ + public override partial DeviceFlowCodesEto Map(DeviceFlowCodes source); + public override partial void Map(DeviceFlowCodes source, DeviceFlowCodesEto destination); +} + +