Browse Source

Merge branch 'dev' into yekalkan-mapper-update

pull/23644/head
Yunus Emre Kalkan 1 year ago
parent
commit
7c5127c9e3
  1. 2
      docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/POST.md
  2. 27
      docs/en/studio/release-notes.md
  3. 2
      docs/en/studio/version-mapping.md
  4. 2
      docs/en/tutorials/modular-crm/part-05.md
  5. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/WebRequestResources.cs
  6. 136
      framework/src/Volo.Abp.Mapperly/Volo/Abp/Mapperly/MapperlyAutoObjectMappingProvider.cs
  7. 135
      framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs
  8. 81
      framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMappingHelper.cs
  9. 54
      framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/AbpMapperlyModule_Basic_Tests.cs
  10. 1
      modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj
  11. 21
      modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AbpAccountApplicationMappers.cs
  12. 10
      modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AbpAccountApplicationModule.cs
  13. 15
      modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AbpAccountApplicationModuleAutoMapperProfile.cs
  14. 20
      modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs
  15. 27
      modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorMappers.cs
  16. 15
      modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs
  17. 2
      modules/account/src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.csproj
  18. 15
      modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs
  19. 13
      modules/account/src/Volo.Abp.Account.Web/AbpAccountWebMappers.cs
  20. 14
      modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs
  21. 2
      modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj
  22. 46
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json
  23. 2
      modules/identity/src/Volo.Abp.Identity.Application/Volo.Abp.Identity.Application.csproj
  24. 19
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/AbpIdentityApplicationMappers.cs
  25. 11
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/AbpIdentityApplicationModule.cs
  26. 15
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/AbpIdentityApplicationModuleAutoMapperProfile.cs
  27. 18
      modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorAutoMapperProfile.cs
  28. 25
      modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMappers.cs
  29. 13
      modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorModule.cs
  30. 2
      modules/identity/src/Volo.Abp.Identity.Blazor/Volo.Abp.Identity.Blazor.csproj
  31. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj
  32. 11
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs
  33. 33
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDomainMappers.cs
  34. 15
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDomainMappingProfile.cs
  35. 57
      modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs
  36. 94
      modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebMappers.cs
  37. 11
      modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs
  38. 2
      modules/identity/src/Volo.Abp.Identity.Web/Volo.Abp.Identity.Web.csproj
  39. 6
      npm/ng-packs/packages/core/src/lib/abstracts/auth.guard.ts
  40. 10
      npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts
  41. 9
      npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts
  42. 37
      npm/ng-packs/packages/oauth/src/lib/guards/oauth.guard.ts
  43. 7
      npm/ng-packs/packages/oauth/src/lib/providers/oauth-module-config.provider.ts

2
docs/en/Community-Articles/2025-07-26-Separate-Tenant-Schema/POST.md

@ -22,7 +22,7 @@ In the shared database model, all the application data stored in a single physic
![single-shared-database](single-shared-database.png)
This is the default behavior when you [create a new ABP application](https://abp.io/docs/latest/get-started), because it is simple to begin with and proper for must applications.
This is the default behavior when you [create a new ABP application](https://abp.io/docs/latest/get-started), because it is simple to begin with and proper for most applications.
In this model, a single database table may contain data of multiple tenants. Each row in these tables have a `TenantId` field which is used to distinguish the tenant data and isolate a tenant's data from other tenant users. To make your entities multi-tenant aware, all you have to do is to implement the `IMultiTenant` interface provided by the ABP Framework.

27
docs/en/studio/release-notes.md

@ -2,6 +2,33 @@
This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version.
## 1.1.2 (2025-07-31)
* Upgraded template dependencies for ABP Framework and LeptonX. (targeting ABP `9.2.3`)
* Configured LeptonX Lite logos in the templates.
* Added browser tab memory feature to remember previously selected tabs.
* Enhanced tools section with default credentials display for first-time tool usage.
* Improved module and package loading with better error handling.
## 1.1.1 (2025-07-22)
* Enhanced tools section with clear cookies option.
* Fixed language management module name display for imported modules.
* Improved update window messaging with "Skip this version" option.
* Fixed Docker Compose file issues in microservice template.
* Resolved RabbitMQ tool cookie problems.
## 1.1.0 (2025-07-16)
* Upgraded template dependencies for ABP Framework and LeptonX. (targeting ABP `9.2.2`)
* Enhanced UI scaling for all windows and improved user experience.
* Added tools section in solution runner main area with basic Grafana dashboard for microservice template.
* Improved container management during application building.
* Enhanced background task exception handling.
* Added public account module package reference to Blazor WebApp client.
* Fixed tenant database context updating errors.
* Improved optional module selection UI with better documentation integration.
## 1.0.2 (2025-06-24)
* Enhanced the ABP NuGet package installation experience.

2
docs/en/studio/version-mapping.md

@ -4,6 +4,8 @@ This document provides a general overview of the relationship between various ve
| **ABP Studio Version** | **ABP Version of Startup Template** |
|------------------------|---------------------------|
| 1.1.2 | 9.2.3 |
| 1.1.0 - 1.1.1 | 9.2.2 |
| 1.0.2 | 9.2.1 |
| 1.0.1 | 9.2.0 |
| 1.0.0 | 9.2.0 |

2
docs/en/tutorials/modular-crm/part-05.md

@ -167,7 +167,7 @@ The `ReplaceDbContext` attribute allows the use of the `ModularCrmDbContext` cla
````csharp
public class ModularCrmDbContext :
AbpDbContext<ModularCrmDbContext>,
IProductsDbContext,
ICatalogDbContext,
IOrderingDbContext //NEW: IMPLEMENT THE INTERFACE
{
public DbSet<Product> Products { get; set; }

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Resources/WebRequestResources.cs

@ -30,6 +30,8 @@ public class WebRequestResources : IWebRequestResources, IScopedDependency
}
Resources.Add(path, resources);
return resources;
// Create a new list as return value to avoid any changes to the list will affect the value in Resources dictionary.
return resources.ToList();
}
}

136
framework/src/Volo.Abp.Mapperly/Volo/Abp/Mapperly/MapperlyAutoObjectMappingProvider.cs

@ -1,5 +1,9 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
@ -19,6 +23,8 @@ public class MapperlyAutoObjectMappingProvider<TContext> : MapperlyAutoObjectMap
public class MapperlyAutoObjectMappingProvider : IAutoObjectMappingProvider
{
protected static readonly ConcurrentDictionary<string, Func<object, object, object, object?>> MapCache = new();
protected IServiceProvider ServiceProvider { get; }
public MapperlyAutoObjectMappingProvider(IServiceProvider serviceProvider)
@ -28,6 +34,11 @@ public class MapperlyAutoObjectMappingProvider : IAutoObjectMappingProvider
public virtual TDestination Map<TSource, TDestination>(object source)
{
if (TryToMapCollection<TSource, TDestination>((TSource)source, default, out var collectionResult))
{
return collectionResult;
}
var mapper = ServiceProvider.GetService<IAbpMapperlyMapper<TSource, TDestination>>();
if (mapper != null)
{
@ -54,6 +65,11 @@ public class MapperlyAutoObjectMappingProvider : IAutoObjectMappingProvider
public virtual TDestination Map<TSource, TDestination>(TSource source, TDestination destination)
{
if (TryToMapCollection<TSource, TDestination>(source, destination, out var collectionResult))
{
return collectionResult;
}
var mapper = ServiceProvider.GetService<IAbpMapperlyMapper<TSource, TDestination>>();
if (mapper != null)
{
@ -80,6 +96,126 @@ public class MapperlyAutoObjectMappingProvider : IAutoObjectMappingProvider
$" {TypeHelper.GetFullNameHandlingNullableAndGenerics(typeof(IAbpReverseMapperlyMapper<TSource, TDestination>))} was found");
}
protected virtual bool TryToMapCollection<TSource, TDestination>(TSource source, TDestination? destination, out TDestination collectionResult)
{
if (!ObjectMappingHelper.IsCollectionGenericType<TSource, TDestination>(out var sourceArgumentType, out var destinationArgumentType, out var definitionGenericType))
{
collectionResult = default!;
return false;
}
var mapperType = typeof(IAbpMapperlyMapper<,>).MakeGenericType(sourceArgumentType, destinationArgumentType);
var mapper = ServiceProvider.GetService(mapperType);
if (mapper == null)
{
mapperType = typeof(IAbpReverseMapperlyMapper<,>).MakeGenericType(destinationArgumentType, sourceArgumentType);
mapper = ServiceProvider.GetService(mapperType);
if (mapper == null)
{
//skip, no specific mapper
collectionResult = default!;
return false;
}
}
var invoker = MapCache.GetOrAdd(
$"{mapperType.FullName}_{(destination == null ? "MapMethodWithSingleParameter" : "MapMethodWithDoubleParameters")}",
_ => CreateMapDelegate(mapperType, sourceArgumentType, destinationArgumentType, destination != null));
var sourceList = source!.As<IList>();
var result = definitionGenericType.IsGenericType
? Activator.CreateInstance(definitionGenericType.MakeGenericType(destinationArgumentType))!.As<IList>()
: Array.CreateInstance(destinationArgumentType, sourceList.Count);
if (destination != null && !destination.GetType().IsArray)
{
//Clear destination collection if destination not an array, We won't change array just same behavior as AutoMapper.
destination.As<IList>().Clear();
}
for (var i = 0; i < sourceList.Count; i++)
{
var invokeResult = destination == null
? invoker(this, sourceList[i]!, null!)
: invoker(this, sourceList[i]!, Activator.CreateInstance(destinationArgumentType)!);
if (definitionGenericType.IsGenericType)
{
result.Add(invokeResult);
destination?.As<IList>().Add(invokeResult);
}
else
{
result[i] = invokeResult;
}
}
if (destination != null && destination.GetType().IsArray)
{
//Return the new collection if destination is an array, We won't change array just same behavior as AutoMapper.
collectionResult = (TDestination)result;
return true;
}
//Return the destination if destination exists. The parameter reference equals with return object.
collectionResult = destination ?? (TDestination)result;
return true;
}
protected virtual Func<object, object, object, object?> CreateMapDelegate(
Type mapperType,
Type sourceArgumentType,
Type destinationArgumentType,
bool hasDestination)
{
var methods = typeof(MapperlyAutoObjectMappingProvider)
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(x => x.Name == nameof(Map))
.Where(x =>
{
var parameters = x.GetParameters();
return (hasDestination || parameters.Length == 1) &&
(!hasDestination || parameters.Length == 2);
})
.ToList();
if (methods.Count == 0)
{
throw new AbpException($"Could not find a method named '{nameof(Map)}'" +
$" with parameters({(hasDestination ? sourceArgumentType + ", " + destinationArgumentType : sourceArgumentType.ToString())})" +
$" in the type '{mapperType}'.");
}
if (methods.Count > 1)
{
throw new AbpException($"Found more than one method named '{nameof(Map)}'" +
$" with parameters({(hasDestination ? sourceArgumentType + ", " + destinationArgumentType : sourceArgumentType.ToString())})" +
$" in the type '{mapperType}'.");
}
var method = methods[0].MakeGenericMethod(sourceArgumentType, destinationArgumentType);
var instanceParam = Expression.Parameter(typeof(object), "mapper");
var sourceParam = Expression.Parameter(typeof(object), "source");
var destinationParam = Expression.Parameter(typeof(object), "destination");
var instanceCast = Expression.Convert(instanceParam, method.DeclaringType!);
var callParams = new List<Expression>
{
Expression.Convert(sourceParam, sourceArgumentType)
};
if (hasDestination)
{
callParams.Add(Expression.Convert(destinationParam, destinationArgumentType));
}
var call = Expression.Call(instanceCast, method, callParams);
var callConvert = Expression.Convert(call, typeof(object));
return Expression.Lambda<Func<object, object, object, object?>>(callConvert, instanceParam, sourceParam, destinationParam).Compile();
}
protected virtual ExtraPropertyDictionary GetExtraProperties<TDestination>(TDestination destination)
{
var extraProperties = new ExtraPropertyDictionary();

135
framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs

@ -5,6 +5,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Volo.Abp.DependencyInjection;
@ -25,7 +26,7 @@ public class DefaultObjectMapper<TContext> : DefaultObjectMapper, IObjectMapper<
public class DefaultObjectMapper : IObjectMapper, ITransientDependency
{
protected static ConcurrentDictionary<string, MethodInfo> MethodInfoCache { get; } = new ConcurrentDictionary<string, MethodInfo>();
protected static readonly ConcurrentDictionary<string, Func<object, object, object, object?>> MapCache = new();
public IAutoObjectMappingProvider AutoObjectMappingProvider { get; }
protected IServiceProvider ServiceProvider { get; }
@ -122,7 +123,7 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
protected virtual bool TryToMapCollection<TSource, TDestination>(IServiceScope serviceScope, TSource source, TDestination? destination, out TDestination collectionResult)
{
if (!IsCollectionGenericType<TSource, TDestination>(out var sourceArgumentType, out var destinationArgumentType, out var definitionGenericType))
if (!ObjectMappingHelper.IsCollectionGenericType<TSource, TDestination>(out var sourceArgumentType, out var destinationArgumentType, out var definitionGenericType))
{
collectionResult = default!;
return false;
@ -137,46 +138,9 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
return false;
}
var cacheKey = $"{mapperType.FullName}_{(destination == null ? "MapMethodWithSingleParameter" : "MapMethodWithDoubleParameters")}";
var method = MethodInfoCache.GetOrAdd(
cacheKey,
_ =>
{
var methods = specificMapper
.GetType()
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(x => x.Name == nameof(IObjectMapper<object, object>.Map))
.Where(x =>
{
var parameters = x.GetParameters();
if (destination == null && parameters.Length != 1 ||
destination != null && parameters.Length != 2 ||
parameters[0].ParameterType != sourceArgumentType)
{
return false;
}
return destination == null || parameters[1].ParameterType == destinationArgumentType;
})
.ToList();
if (methods.IsNullOrEmpty())
{
throw new AbpException($"Could not find a method named '{nameof(IObjectMapper<object, object>.Map)}'" +
$" with parameters({(destination == null ? sourceArgumentType.ToString() : sourceArgumentType + "," + destinationArgumentType)})" +
$" in the type '{mapperType}'.");
}
if (methods.Count > 1)
{
throw new AbpException($"Found more than one method named '{nameof(IObjectMapper<object, object>.Map)}'" +
$" with parameters({(destination == null ? sourceArgumentType.ToString() : sourceArgumentType + "," + destinationArgumentType)})" +
$" in the type '{mapperType}'.");
}
return methods.First();
}
);
var invoker = MapCache.GetOrAdd(
$"{mapperType.FullName}_{(destination == null ? "MapMethodWithSingleParameter" : "MapMethodWithDoubleParameters")}",
_ => CreateMapDelegate(mapperType, sourceArgumentType, destinationArgumentType, destination != null));
var sourceList = source!.As<IList>();
var result = definitionGenericType.IsGenericType
@ -192,8 +156,8 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
for (var i = 0; i < sourceList.Count; i++)
{
var invokeResult = destination == null
? method.Invoke(specificMapper, new [] { sourceList[i] })!
: method.Invoke(specificMapper, new [] { sourceList[i], Activator.CreateInstance(destinationArgumentType)! })!;
? invoker(specificMapper, sourceList[i]!, null!)
: invoker(specificMapper, sourceList[i]!, Activator.CreateInstance(destinationArgumentType)!);
if (definitionGenericType.IsGenericType)
{
@ -218,61 +182,64 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
return true;
}
protected virtual bool IsCollectionGenericType<TSource, TDestination>(out Type sourceArgumentType, out Type destinationArgumentType, out Type definitionGenericType)
protected virtual Func<object, object, object, object?> CreateMapDelegate(
Type mapperType,
Type sourceArgumentType,
Type destinationArgumentType,
bool hasDestination)
{
sourceArgumentType = default!;
destinationArgumentType = default!;
definitionGenericType = default!;
if ((!typeof(TSource).IsGenericType && !typeof(TSource).IsArray) ||
(!typeof(TDestination).IsGenericType && !typeof(TDestination).IsArray))
{
return false;
}
var methods = mapperType
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(x => x.Name == nameof(IObjectMapper<object, object>.Map))
.Where(x =>
{
var parameters = x.GetParameters();
if (!hasDestination && parameters.Length != 1 ||
hasDestination && parameters.Length != 2 ||
parameters[0].ParameterType != sourceArgumentType)
{
return false;
}
var supportedCollectionTypes = new[]
{
typeof(IEnumerable<>),
typeof(ICollection<>),
typeof(Collection<>),
typeof(IList<>),
typeof(List<>)
};
return !hasDestination || parameters[1].ParameterType == destinationArgumentType;
})
.ToList();
if (typeof(TSource).IsGenericType && supportedCollectionTypes.Any(x => x == typeof(TSource).GetGenericTypeDefinition()))
if (methods.Count == 0)
{
sourceArgumentType = typeof(TSource).GenericTypeArguments[0];
throw new AbpException($"Could not find a method named '{nameof(IObjectMapper<object, object>.Map)}'" +
$" with parameters({(hasDestination ? sourceArgumentType + ", " + destinationArgumentType : sourceArgumentType.ToString())})" +
$" in the type '{mapperType}'.");
}
if (typeof(TSource).IsArray)
if (methods.Count > 1)
{
sourceArgumentType = typeof(TSource).GetElementType()!;
throw new AbpException($"Found more than one method named '{nameof(IObjectMapper<object, object>.Map)}'" +
$" with parameters({(hasDestination ? sourceArgumentType + ", " + destinationArgumentType : sourceArgumentType.ToString())})" +
$" in the type '{mapperType}'.");
}
if (sourceArgumentType == default!)
{
return false;
}
var method = methods[0];
definitionGenericType = typeof(List<>);
if (typeof(TDestination).IsGenericType && supportedCollectionTypes.Any(x => x == typeof(TDestination).GetGenericTypeDefinition()))
{
destinationArgumentType = typeof(TDestination).GenericTypeArguments[0];
var instanceParam = Expression.Parameter(typeof(object), "mapper");
var sourceParam = Expression.Parameter(typeof(object), "source");
var destinationParam = Expression.Parameter(typeof(object), "destination");
if (typeof(TDestination).GetGenericTypeDefinition() == typeof(ICollection<>) ||
typeof(TDestination).GetGenericTypeDefinition() == typeof(Collection<>))
{
definitionGenericType = typeof(Collection<>);
}
}
var instanceCast = Expression.Convert(instanceParam, method.DeclaringType!);
var callParams = new List<Expression>
{
Expression.Convert(sourceParam, sourceArgumentType)
};
if (typeof(TDestination).IsArray)
if (hasDestination)
{
destinationArgumentType = typeof(TDestination).GetElementType()!;
definitionGenericType = typeof(Array);
callParams.Add(Expression.Convert(destinationParam, destinationArgumentType));
}
return destinationArgumentType != default!;
var call = Expression.Call(instanceCast, method, callParams);
var callConvert = Expression.Convert(call, typeof(object));
return Expression.Lambda<Func<object, object, object, object?>>(callConvert, instanceParam, sourceParam, destinationParam).Compile();
}
protected virtual TDestination AutoMap<TSource, TDestination>(object source)

81
framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/ObjectMappingHelper.cs

@ -0,0 +1,81 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Volo.Abp.ObjectMapping;
public static class ObjectMappingHelper
{
private static readonly ConcurrentDictionary<(Type, Type), (Type sourceArgumentType, Type destinationArgumentType, Type definitionGenericType)?> Cache = new();
public static bool IsCollectionGenericType<TSource, TDestination>(
out Type sourceArgumentType,
out Type destinationArgumentType,
out Type definitionGenericType)
{
var cached = Cache.GetOrAdd((typeof(TSource), typeof(TDestination)), _ => IsCollectionGenericTypeInternal<TSource, TDestination>());
if (cached == null)
{
sourceArgumentType = destinationArgumentType = definitionGenericType = null!;
return false;
}
(sourceArgumentType, destinationArgumentType, definitionGenericType) = cached.Value;
return true;
}
private static (Type, Type, Type)? IsCollectionGenericTypeInternal<TSource, TDestination>()
{
if (!IsCollectionGenericTypeInternal(typeof(TSource), out var sourceArgumentType, out _) ||
!IsCollectionGenericTypeInternal(typeof(TDestination), out var destinationArgumentType, out var definitionGenericType))
{
return null;
}
return (sourceArgumentType, destinationArgumentType, definitionGenericType);
}
private static bool IsCollectionGenericTypeInternal(Type type, out Type elementType, out Type definitionGenericType)
{
var supportedCollectionTypes = new[]
{
typeof(IEnumerable<>),
typeof(ICollection<>),
typeof(Collection<>),
typeof(IList<>),
typeof(List<>)
};
if (type.IsArray)
{
elementType = type.GetElementType()!;
definitionGenericType = type;
return true;
}
if (type.IsGenericType &&
supportedCollectionTypes.Contains(type.GetGenericTypeDefinition()) ||
type.GetInterfaces().Any(i => i.IsGenericType && supportedCollectionTypes.Contains(i.GetGenericTypeDefinition())))
{
elementType = type.GetGenericArguments()[0];
definitionGenericType = type.GetGenericTypeDefinition();
if (definitionGenericType == typeof(IEnumerable<>) ||
definitionGenericType == typeof(IList<>))
{
definitionGenericType = typeof(List<>);
}
if (definitionGenericType == typeof(ICollection<>))
{
definitionGenericType = typeof(Collection<>);
}
return true;
}
elementType = null!;
definitionGenericType = null!;
return false;
}
}

54
framework/test/Volo.Abp.Mapperly.Tests/Volo/Abp/Mapperly/AbpMapperlyModule_Basic_Tests.cs

@ -1,4 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.JavaScript;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Mapperly.SampleClasses;
@ -41,6 +44,57 @@ public class AbpMapperlyModule_Basic_Tests : AbpIntegratedTest<MapperlyTestModul
dto.Id.ShouldNotBe(Guid.Empty);
}
[Fact]
public void Should_Map_Collection()
{
var dto = _objectMapper.Map<List<MyEntity>, List<MyEntityDto>>(new List<MyEntity>
{
new MyEntity { Number = 42 },
new MyEntity { Number = 43 }
});
dto.Count.ShouldBe(2);
dto[0].Number.ShouldBe(42);
dto[1].Number.ShouldBe(43);
var dto2 = _objectMapper.Map<IReadOnlyList<MyEntity>, MyEntityDto[]>(new List<MyEntity>
{
new MyEntity { Number = 42 },
new MyEntity { Number = 43 }
}.AsReadOnly());
dto2.Length.ShouldBe(2);
dto2[0].Number.ShouldBe(42);
dto2[1].Number.ShouldBe(43);
var dtoList = new List<MyEntityDto>();
{
new MyEntityDto() { Number = 44 };
new MyEntityDto() { Number = 45 };
}
_objectMapper.Map<List<MyEntity>, List<MyEntityDto>>(new List<MyEntity>
{
new MyEntity { Number = 42 },
new MyEntity { Number = 43 }
}, dtoList);
dtoList.Count.ShouldBe(2);
dtoList[0].Number.ShouldBe(42);
dtoList[1].Number.ShouldBe(43);
var dtoArray = dtoList.ToArray();
_objectMapper.Map<IReadOnlyList<MyEntity>, MyEntityDto[]>(new List<MyEntity>
{
new MyEntity { Number = 42 },
new MyEntity { Number = 43 }
}.AsReadOnly(), dtoArray);
dtoArray.Length.ShouldBe(2);
dtoArray[0].Number.ShouldBe(42);
dtoArray[1].Number.ShouldBe(43);
}
[Fact]
public void Should_Map_Enum()
{

1
modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj

@ -21,6 +21,7 @@
<ProjectReference Include="..\..\..\identity\src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.UI.Navigation\Volo.Abp.UI.Navigation.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Emailing\Volo.Abp.Emailing.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Mapperly\Volo.Abp.Mapperly.csproj" />
</ItemGroup>
<ItemGroup>

21
modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AbpAccountApplicationMappers.cs

@ -0,0 +1,21 @@
using Riok.Mapperly.Abstractions;
using Volo.Abp.Identity;
using Volo.Abp.Mapperly;
namespace Volo.Abp.Account;
[Mapper]
[MapExtraProperties]
public partial class IdentityUserToProfileDtoMapper : MapperBase<IdentityUser, ProfileDto>
{
[MapperIgnoreTarget(nameof(ProfileDto.HasPassword))]
public override partial ProfileDto Map(IdentityUser source);
[MapperIgnoreTarget(nameof(ProfileDto.HasPassword))]
public override partial void Map(IdentityUser source, ProfileDto destination);
public override void AfterMap(IdentityUser source, ProfileDto destination)
{
destination.HasPassword = source.PasswordHash != null;
}
}

10
modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AbpAccountApplicationModule.cs

@ -1,4 +1,4 @@
using Volo.Abp.AutoMapper;
using Volo.Abp.Mapperly;
using Volo.Abp.Emailing;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
@ -12,7 +12,8 @@ namespace Volo.Abp.Account;
typeof(AbpAccountApplicationContractsModule),
typeof(AbpIdentityApplicationModule),
typeof(AbpUiNavigationModule),
typeof(AbpEmailingModule)
typeof(AbpEmailingModule),
typeof(AbpMapperlyModule)
)]
public class AbpAccountApplicationModule : AbpModule
{
@ -23,11 +24,6 @@ public class AbpAccountApplicationModule : AbpModule
options.FileSets.AddEmbedded<AbpAccountApplicationModule>();
});
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpAccountApplicationModuleAutoMapperProfile>(validate: true);
});
Configure<AppUrlOptions>(options =>
{
options.Applications["MVC"].Urls[AccountUrlNames.PasswordReset] = "Account/ResetPassword";

15
modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AbpAccountApplicationModuleAutoMapperProfile.cs

@ -1,15 +0,0 @@
using AutoMapper;
using Volo.Abp.Identity;
namespace Volo.Abp.Account;
public class AbpAccountApplicationModuleAutoMapperProfile : Profile
{
public AbpAccountApplicationModuleAutoMapperProfile()
{
CreateMap<IdentityUser, ProfileDto>()
.ForMember(dest => dest.HasPassword,
op => op.MapFrom(src => src.PasswordHash != null))
.MapExtraProperties();
}
}

20
modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs

@ -1,20 +0,0 @@
using AutoMapper;
using Volo.Abp.Account.Blazor.Pages.Account;
using Volo.Abp.AutoMapper;
using Volo.Abp.Identity;
namespace Volo.Abp.Account.Blazor;
public class AbpAccountBlazorAutoMapperProfile : Profile
{
public AbpAccountBlazorAutoMapperProfile()
{
CreateMap<ProfileDto, PersonalInfoModel>()
.MapExtraProperties()
.Ignore(x => x.PhoneNumberConfirmed)
.Ignore(x => x.EmailConfirmed);
CreateMap<PersonalInfoModel, UpdateProfileDto>()
.MapExtraProperties();
}
}

27
modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorMappers.cs

@ -0,0 +1,27 @@
using Riok.Mapperly.Abstractions;
using Volo.Abp.Account.Blazor.Pages.Account;
using Volo.Abp.Mapperly;
using Volo.Abp.Identity;
namespace Volo.Abp.Account.Blazor;
[Mapper]
[MapExtraProperties]
public partial class ProfileDtoToPersonalInfoModelMapper : MapperBase<ProfileDto, PersonalInfoModel>
{
[MapperIgnoreTarget(nameof(PersonalInfoModel.PhoneNumberConfirmed))]
[MapperIgnoreTarget(nameof(PersonalInfoModel.EmailConfirmed))]
public override partial PersonalInfoModel Map(ProfileDto source);
[MapperIgnoreTarget(nameof(PersonalInfoModel.PhoneNumberConfirmed))]
[MapperIgnoreTarget(nameof(PersonalInfoModel.EmailConfirmed))]
public override partial void Map(ProfileDto source, PersonalInfoModel destination);
}
[Mapper]
[MapExtraProperties]
public partial class PersonalInfoModelToUpdateProfileDtoMapper : MapperBase<PersonalInfoModel, UpdateProfileDto>
{
public override partial UpdateProfileDto Map(PersonalInfoModel source);
public override partial void Map(PersonalInfoModel source, UpdateProfileDto destination);
}

15
modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs

@ -2,7 +2,7 @@
using Volo.Abp.Account.Blazor.Pages.Account;
using Volo.Abp.AspNetCore.Components.Web.Theming;
using Volo.Abp.AspNetCore.Components.Web.Theming.Routing;
using Volo.Abp.AutoMapper;
using Volo.Abp.Mapperly;
using Volo.Abp.Modularity;
using Volo.Abp.ObjectExtending;
using Volo.Abp.ObjectExtending.Modularity;
@ -13,21 +13,16 @@ namespace Volo.Abp.Account.Blazor;
[DependsOn(
typeof(AbpAspNetCoreComponentsWebThemingModule),
typeof(AbpAutoMapperModule),
typeof(AbpMapperlyModule),
typeof(AbpAccountApplicationContractsModule)
)]
public class AbpAccountBlazorModule : AbpModule
{
private readonly static OneTimeRunner OneTimeRunner = new OneTimeRunner();
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<AbpAccountBlazorModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpAccountBlazorAutoMapperProfile>(validate: true);
});
context.Services.AddMapperlyObjectMapper<AbpAccountBlazorModule>();
Configure<AbpNavigationOptions>(options =>
{
@ -39,7 +34,7 @@ public class AbpAccountBlazorModule : AbpModule
options.AdditionalAssemblies.Add(typeof(AbpAccountBlazorModule).Assembly);
});
}
public override void PostConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>

2
modules/account/src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.csproj

@ -10,7 +10,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Components.Web.Theming\Volo.Abp.AspNetCore.Components.Web.Theming.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Mapperly\Volo.Abp.Mapperly.csproj" />
</ItemGroup>
<ItemGroup>

15
modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs

@ -1,15 +0,0 @@
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.Identity;
using AutoMapper;
using Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo;
namespace Volo.Abp.Account.Web;
public class AbpAccountWebAutoMapperProfile : Profile
{
public AbpAccountWebAutoMapperProfile()
{
CreateMap<ProfileDto, AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel>()
.MapExtraProperties();
}
}

13
modules/account/src/Volo.Abp.Account.Web/AbpAccountWebMappers.cs

@ -0,0 +1,13 @@
using Riok.Mapperly.Abstractions;
using Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo;
using Volo.Abp.Mapperly;
namespace Volo.Abp.Account.Web;
[Mapper]
[MapExtraProperties]
public partial class ProfileDtoToPersonalInfoModelMapper : MapperBase<ProfileDto, AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel>
{
public override partial AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel Map(ProfileDto source);
public override partial void Map(ProfileDto source, AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel destination);
}

14
modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs

@ -8,7 +8,7 @@ using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
using Volo.Abp.AutoMapper;
using Volo.Abp.Mapperly;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http.ProxyScripting.Generators.JQuery;
using Volo.Abp.Identity.AspNetCore;
@ -24,14 +24,14 @@ namespace Volo.Abp.Account.Web;
[DependsOn(
typeof(AbpAccountApplicationContractsModule),
typeof(AbpIdentityAspNetCoreModule),
typeof(AbpAutoMapperModule),
typeof(AbpMapperlyModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule),
typeof(AbpExceptionHandlingModule)
)]
public class AbpAccountWebModule : AbpModule
{
private readonly static OneTimeRunner OneTimeRunner = new OneTimeRunner();
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
@ -59,11 +59,7 @@ public class AbpAccountWebModule : AbpModule
ConfigureProfileManagementPage();
context.Services.AddAutoMapperObjectMapper<AbpAccountWebModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpAccountWebAutoMapperProfile>(validate: true);
});
context.Services.AddMapperlyObjectMapper<AbpAccountWebModule>();
Configure<DynamicJavaScriptProxyOptions>(options =>
{
@ -96,7 +92,7 @@ public class AbpAccountWebModule : AbpModule
});
}
public override void PostConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>

2
modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj

@ -39,7 +39,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\identity\src\Volo.Abp.Identity.AspNetCore\Volo.Abp.Identity.AspNetCore.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Mapperly\Volo.Abp.Mapperly.csproj" />
<ProjectReference Include="..\Volo.Abp.Account.Application.Contracts\Volo.Abp.Account.Application.Contracts.csproj" />
</ItemGroup>

46
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json

@ -15,6 +15,7 @@
"CmsKit.Ratings": "Hodnocení",
"CmsKit.Reactions": "Reakce",
"CmsKit.Tags": "Tagy",
"CmsKit.MarkedItems": "Označené položky",
"CmsKit:0002": "Obsah již existuje!",
"CmsKit:0003": "Entitu {0} nelze označit.",
"CmsKit:Blog:0001": "Daný slimák ({Slug}) již existuje!",
@ -26,8 +27,19 @@
"CmsKit:Rating:0001": "Entitu {EntityType} nelze hodnotit.",
"CmsKit:Reaction:0001": "Entita {EntityType} nemůže mít reakce.",
"CmsKit:Tag:0002": "Entitu nelze označit!",
"CmsKit:MarkedItem:ToggleConfirmation": "Opravdu chcete přepnout označenou položku?",
"ToggleFavorite": "Přidat/Odebrat z oblíbených",
"FavoritesFilterMessage": "Pro filtrování oblíbených se přihlaste",
"FilterOnFavorites": "Filtrovat podle oblíbených",
"CommentAuthorizationExceptionMessage": "Tyto komentáře nejsou povoleny pro veřejné zobrazení.",
"CmsKit:Modals:Login": "Přihlášení",
"CmsKit:Modals:LoginModalDefaultMessage": "Pro pokračování se přihlaste!",
"CmsKit:Modals:YouAreNotAuthenticated": "Tato operace pro vás není autorizována.",
"CommentDeletionConfirmationMessage": "Tento komentář a všechny odpovědi budou smazány!",
"CmsKit:MarkedItem:0001": "Entitu {EntityType} nelze označit.",
"CmsKit:MarkedItem:0002": "Pro typ entity '{EntityType}' nebyla nalezena žádná definice.",
"CmsKit:MarkedItem:0003": "Definice pro typ entity '{EntityType}' již existuje. Každý typ entity by měl mít pouze jednu definici.",
"CmsKit:MarkedItem:LoginMessage": "Pro označení této položky se přihlaste.",
"Comments": "Komentáře",
"Content": "Obsah",
"ContentDeletionConfirmationMessage": "Opravdu chcete tento obsah smazat?",
@ -134,6 +146,7 @@
"SamplePageMessage": "Ukázková stránka pro modul Pro",
"SaveChanges": "Uložit změny",
"Script": "Skript",
"SelectLayout": "Vybrat rozložení",
"SelectAll": "Vybrat vše",
"Send": "Poslat",
"SendMessage": "Poslat zprávu",
@ -216,6 +229,8 @@
"Feature:ReactionEnableDescription": "Systém reakcí CMS Kit, který umožňuje uživatelům posílat reakce entitám, jako jsou BlogPost, Komentáře atd.",
"Feature:TagEnable": "Označování",
"Feature:TagEnableDescription": "Systém značek CMS Kit, který umožňuje označování entit, jako je BlogPost.",
"Feature:MarkedItemEnable": "Označená položka",
"Feature:MarkedItemEnableDescription": "Systém označování CMS Kit, který umožňuje uživatelům označovat entity jako oblíbené.",
"DeleteBlogPostMessage": "Blog bude smazán. Jsi si jistá?",
"CaptchaCode": "Captcha kód",
"CommentTextRequired": "Komentář je povinný",
@ -230,6 +245,37 @@
"TagsHelpText": "Značky by měly být odděleny čárkami (např.: tag1, tag2, tag3)",
"ThisPartOfContentCouldntBeLoaded": "Tato část obsahu nemohla být načtena.",
"DuplicateCommentAttemptMessage": "Byl zjištěn duplicitní pokus o vložení komentáře. Váš komentář již byl odeslán.",
"NoBlogPostYet": "Zatím žádný blogový příspěvek!",
"CmsKit:Comment": "Komentář",
"CmsKitCommentOptions:RequireApprovement": "Vyžadovat schválení komentářů",
"CmsKitCommentOptions:RequireApprovementDescription": "Když je povoleno, komentáře budou vyžadovat schválení před zveřejněním.",
"CommentFilter:ApproveState": "Stav schválení",
"ApproveState": "Stav schválení",
"CommentFilter:0": "Vše",
"CommentFilter:1": "Schváleno",
"CommentFilter:2": "Zamítnuto",
"CommentFilter:4": "Čeká",
"ApprovedSuccessfully": "Úspěšně schváleno",
"ApprovalRevokedSuccessfully": "Schválení úspěšně odvoláno",
"Approve": "Schválit",
"Disapproved": "Zamítnuto",
"CommentAlertMessage": "Čeká {0} komentářů na schválení",
"Settings:Menu:CmsKit": "CMS",
"CommentsAwaitingApproval": "Komentáře čekající na schválení",
"JustNow": "Právě teď",
"MinuteAgo": "před 1 minutou",
"MinutesAgo": "před {0} minutami",
"HourAgo": "před 1 hodinou",
"HoursAgo": "před {0} hodinami",
"YesterdayAt": "Včera v {0}",
"DayAt": "{0} v {1}",
"MonthDayAt": "{0} {1} v {2}",
"FullDate": "{0} {1} {2}",
"Minute": "m",
"Hour": "h",
"Day": "d",
"Week": "t",
"CommentSubmittedForApproval": "Váš komentář byl odeslán ke schválení.",
"ChooseAnActionForBlog": "Vyberte akci pro blog",
"AssignBlogPostsToOtherBlog": "Přiřaďte blogové příspěvky k jinému blogu",
"SelectAnBlogToAssign": "Vyberte blog, ke kterému chcete přiřadit blogové příspěvky",

2
modules/identity/src/Volo.Abp.Identity.Application/Volo.Abp.Identity.Application.csproj

@ -18,7 +18,7 @@
<ProjectReference Include="..\Volo.Abp.Identity.Application.Contracts\Volo.Abp.Identity.Application.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" />
<ProjectReference Include="..\..\..\permission-management\src\Volo.Abp.PermissionManagement.Application\Volo.Abp.PermissionManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Mapperly\Volo.Abp.Mapperly.csproj" />
</ItemGroup>
</Project>

19
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/AbpIdentityApplicationMappers.cs

@ -0,0 +1,19 @@
using Riok.Mapperly.Abstractions;
using Volo.Abp.Identity;
using Volo.Abp.Mapperly;
[Mapper]
[MapExtraProperties]
public partial class IdentityUserToIdentityUserDtoMapper : MapperBase<IdentityUser, IdentityUserDto>
{
public override partial IdentityUserDto Map(IdentityUser source);
public override partial void Map(IdentityUser source, IdentityUserDto destination);
}
[Mapper]
[MapExtraProperties]
public partial class IdentityRoleToIdentityRoleDtoMapper : MapperBase<IdentityRole, IdentityRoleDto>
{
public override partial IdentityRoleDto Map(IdentityRole source);
public override partial void Map(IdentityRole source, IdentityRoleDto destination);
}

11
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/AbpIdentityApplicationModule.cs

@ -1,5 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.Mapperly;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
@ -8,18 +8,13 @@ namespace Volo.Abp.Identity;
[DependsOn(
typeof(AbpIdentityDomainModule),
typeof(AbpIdentityApplicationContractsModule),
typeof(AbpAutoMapperModule),
typeof(AbpMapperlyModule),
typeof(AbpPermissionManagementApplicationModule)
)]
public class AbpIdentityApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<AbpIdentityApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpIdentityApplicationModuleAutoMapperProfile>(validate: true);
});
context.Services.AddMapperlyObjectMapper<AbpIdentityApplicationModule>();
}
}

15
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/AbpIdentityApplicationModuleAutoMapperProfile.cs

@ -1,15 +0,0 @@
using AutoMapper;
namespace Volo.Abp.Identity;
public class AbpIdentityApplicationModuleAutoMapperProfile : Profile
{
public AbpIdentityApplicationModuleAutoMapperProfile()
{
CreateMap<IdentityUser, IdentityUserDto>()
.MapExtraProperties();
CreateMap<IdentityRole, IdentityRoleDto>()
.MapExtraProperties();
}
}

18
modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorAutoMapperProfile.cs

@ -1,18 +0,0 @@
using AutoMapper;
using Volo.Abp.AutoMapper;
namespace Volo.Abp.Identity.Blazor;
public class AbpIdentityBlazorAutoMapperProfile : Profile
{
public AbpIdentityBlazorAutoMapperProfile()
{
CreateMap<IdentityUserDto, IdentityUserUpdateDto>()
.MapExtraProperties()
.Ignore(x => x.Password)
.Ignore(x => x.RoleNames);
CreateMap<IdentityRoleDto, IdentityRoleUpdateDto>()
.MapExtraProperties();
}
}

25
modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMappers.cs

@ -0,0 +1,25 @@
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Volo.Abp.Identity.Blazor;
[Mapper]
[MapExtraProperties]
public partial class IdentityUserDtoToIdentityUserUpdateDtoMapper : MapperBase<IdentityUserDto, IdentityUserUpdateDto>
{
[MapperIgnoreTarget(nameof(IdentityUserUpdateDto.Password))]
[MapperIgnoreTarget(nameof(IdentityUserUpdateDto.RoleNames))]
public override partial IdentityUserUpdateDto Map(IdentityUserDto source);
[MapperIgnoreTarget(nameof(IdentityUserUpdateDto.Password))]
[MapperIgnoreTarget(nameof(IdentityUserUpdateDto.RoleNames))]
public override partial void Map(IdentityUserDto source, IdentityUserUpdateDto destination);
}
[Mapper]
[MapExtraProperties]
public partial class IdentityRoleDtoToIdentityRoleUpdateDtoMapper : MapperBase<IdentityRoleDto, IdentityRoleUpdateDto>
{
public override partial IdentityRoleUpdateDto Map(IdentityRoleDto source);
public override partial void Map(IdentityRoleDto source, IdentityRoleUpdateDto destination);
}

13
modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorModule.cs

@ -1,7 +1,7 @@
using Localization.Resources.AbpUi;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Components.Web.Theming.Routing;
using Volo.Abp.AutoMapper;
using Volo.Abp.Mapperly;
using Volo.Abp.BlazoriseUI;
using Volo.Abp.Identity.Localization;
using Volo.Abp.Localization;
@ -16,7 +16,7 @@ namespace Volo.Abp.Identity.Blazor;
[DependsOn(
typeof(AbpIdentityApplicationContractsModule),
typeof(AbpAutoMapperModule),
typeof(AbpMapperlyModule),
typeof(AbpPermissionManagementBlazorModule),
typeof(AbpBlazoriseUIModule)
)]
@ -26,12 +26,7 @@ public class AbpIdentityBlazorModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<AbpIdentityBlazorModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpIdentityBlazorAutoMapperProfile>(validate: true);
});
context.Services.AddMapperlyObjectMapper<AbpIdentityBlazorModule>();
Configure<AbpNavigationOptions>(options =>
{
@ -42,7 +37,7 @@ public class AbpIdentityBlazorModule : AbpModule
{
options.AdditionalAssemblies.Add(typeof(AbpIdentityBlazorModule).Assembly);
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources

2
modules/identity/src/Volo.Abp.Identity.Blazor/Volo.Abp.Identity.Blazor.csproj

@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Mapperly\Volo.Abp.Mapperly.csproj" />
<ProjectReference Include="..\..\..\permission-management\src\Volo.Abp.PermissionManagement.Blazor\Volo.Abp.PermissionManagement.Blazor.csproj" />
</ItemGroup>

2
modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj

@ -23,7 +23,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\users\src\Volo.Abp.Users.Domain\Volo.Abp.Users.Domain.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Mapperly\Volo.Abp.Mapperly.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
</ItemGroup>

11
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Volo.Abp.AutoMapper;
using Volo.Abp.Mapperly;
using Volo.Abp.Domain;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Modularity;
@ -19,7 +19,7 @@ namespace Volo.Abp.Identity;
typeof(AbpDddDomainModule),
typeof(AbpIdentityDomainSharedModule),
typeof(AbpUsersDomainModule),
typeof(AbpAutoMapperModule)
typeof(AbpMapperlyModule)
)]
public class AbpIdentityDomainModule : AbpModule
{
@ -35,12 +35,7 @@ public class AbpIdentityDomainModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<AbpIdentityDomainModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<IdentityDomainMappingProfile>(validate: true);
});
context.Services.AddMapperlyObjectMapper<AbpIdentityDomainModule>();
Configure<AbpDistributedEntityEventOptions>(options =>
{

33
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDomainMappers.cs

@ -0,0 +1,33 @@
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
using Volo.Abp.Users;
namespace Volo.Abp.Identity;
[Mapper]
public partial class IdentityUserToUserEtoMapper : MapperBase<IdentityUser, UserEto>
{
public override partial UserEto Map(IdentityUser source);
public override partial void Map(IdentityUser source, UserEto destination);
}
[Mapper]
public partial class IdentityClaimTypeToIdentityClaimTypeEtoMapper : MapperBase<IdentityClaimType, IdentityClaimTypeEto>
{
public override partial IdentityClaimTypeEto Map(IdentityClaimType source);
public override partial void Map(IdentityClaimType source, IdentityClaimTypeEto destination);
}
[Mapper]
public partial class IdentityRoleToIdentityRoleEtoMapper : MapperBase<IdentityRole, IdentityRoleEto>
{
public override partial IdentityRoleEto Map(IdentityRole source);
public override partial void Map(IdentityRole source, IdentityRoleEto destination);
}
[Mapper]
public partial class OrganizationUnitToOrganizationUnitEtoMapper : MapperBase<OrganizationUnit, OrganizationUnitEto>
{
public override partial OrganizationUnitEto Map(OrganizationUnit source);
public override partial void Map(OrganizationUnit source, OrganizationUnitEto destination);
}

15
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDomainMappingProfile.cs

@ -1,15 +0,0 @@
using AutoMapper;
using Volo.Abp.Users;
namespace Volo.Abp.Identity;
public class IdentityDomainMappingProfile : Profile
{
public IdentityDomainMappingProfile()
{
CreateMap<IdentityUser, UserEto>();
CreateMap<IdentityClaimType, IdentityClaimTypeEto>();
CreateMap<IdentityRole, IdentityRoleEto>();
CreateMap<OrganizationUnit, OrganizationUnitEto>();
}
}

57
modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs

@ -1,57 +0,0 @@
using AutoMapper;
using Volo.Abp.AutoMapper;
using Volo.Abp.Identity.Web.Pages.Identity.Roles;
using CreateUserModalModel = Volo.Abp.Identity.Web.Pages.Identity.Users.CreateModalModel;
using EditUserModalModel = Volo.Abp.Identity.Web.Pages.Identity.Users.EditModalModel;
namespace Volo.Abp.Identity.Web;
public class AbpIdentityWebAutoMapperProfile : Profile
{
public AbpIdentityWebAutoMapperProfile()
{
CreateUserMappings();
CreateRoleMappings();
}
protected virtual void CreateUserMappings()
{
//List
CreateMap<IdentityUserDto, EditUserModalModel.UserInfoViewModel>()
.Ignore(x => x.Password);
//CreateModal
CreateMap<CreateUserModalModel.UserInfoViewModel, IdentityUserCreateDto>()
.MapExtraProperties()
.ForMember(dest => dest.RoleNames, opt => opt.Ignore());
CreateMap<IdentityRoleDto, CreateUserModalModel.AssignedRoleViewModel>()
.ForMember(dest => dest.IsAssigned, opt => opt.Ignore());
//EditModal
CreateMap<EditUserModalModel.UserInfoViewModel, IdentityUserUpdateDto>()
.MapExtraProperties()
.ForMember(dest => dest.RoleNames, opt => opt.Ignore());
CreateMap<IdentityRoleDto, EditUserModalModel.AssignedRoleViewModel>()
.ForMember(dest => dest.IsAssigned, opt => opt.Ignore());
CreateMap<IdentityUserDto, EditUserModalModel.DetailViewModel>()
.ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
.ForMember(dest => dest.ModifiedBy, opt => opt.Ignore());
}
protected virtual void CreateRoleMappings()
{
//List
CreateMap<IdentityRoleDto, EditModalModel.RoleInfoModel>();
//CreateModal
CreateMap<CreateModalModel.RoleInfoModel, IdentityRoleCreateDto>()
.MapExtraProperties();
//EditModal
CreateMap<EditModalModel.RoleInfoModel, IdentityRoleUpdateDto>()
.MapExtraProperties();
}
}

94
modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebMappers.cs

@ -0,0 +1,94 @@
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
using Volo.Abp.Identity.Web.Pages.Identity.Roles;
using CreateUserModalModel = Volo.Abp.Identity.Web.Pages.Identity.Users.CreateModalModel;
using EditUserModalModel = Volo.Abp.Identity.Web.Pages.Identity.Users.EditModalModel;
namespace Volo.Abp.Identity.Web;
[Mapper]
public partial class IdentityUserDtoToEditUserModalModelUserInfoViewModelMapper : MapperBase<IdentityUserDto, EditUserModalModel.UserInfoViewModel>
{
[MapperIgnoreTarget(nameof(EditUserModalModel.UserInfoViewModel.Password))]
public override partial EditUserModalModel.UserInfoViewModel Map(IdentityUserDto source);
[MapperIgnoreTarget(nameof(EditUserModalModel.UserInfoViewModel.Password))]
public override partial void Map(IdentityUserDto source, EditUserModalModel.UserInfoViewModel destination);
}
[Mapper]
[MapExtraProperties]
public partial class CreateUserModalModelUserInfoViewModelToIdentityUserCreateDtoMapper : MapperBase<CreateUserModalModel.UserInfoViewModel, IdentityUserCreateDto>
{
[MapperIgnoreTarget(nameof(IdentityUserCreateDto.RoleNames))]
public override partial IdentityUserCreateDto Map(CreateUserModalModel.UserInfoViewModel source);
[MapperIgnoreTarget(nameof(IdentityUserCreateDto.RoleNames))]
public override partial void Map(CreateUserModalModel.UserInfoViewModel source, IdentityUserCreateDto destination);
}
[Mapper]
[MapExtraProperties]
public partial class IdentityRoleDtoToCreateUserModalModelAssignedRoleViewModelMapper : MapperBase<IdentityRoleDto, CreateUserModalModel.AssignedRoleViewModel>
{
[MapperIgnoreTarget(nameof(CreateUserModalModel.AssignedRoleViewModel.IsAssigned))]
public override partial CreateUserModalModel.AssignedRoleViewModel Map(IdentityRoleDto source);
[MapperIgnoreTarget(nameof(CreateUserModalModel.AssignedRoleViewModel.IsAssigned))]
public override partial void Map(IdentityRoleDto source, CreateUserModalModel.AssignedRoleViewModel destination);
}
[Mapper]
public partial class EditUserModalModelUserInfoViewModelToIdentityUserUpdateDtoMapper : MapperBase<EditUserModalModel.UserInfoViewModel, IdentityUserUpdateDto>
{
[MapperIgnoreTarget(nameof(IdentityUserUpdateDto.RoleNames))]
public override partial IdentityUserUpdateDto Map(EditUserModalModel.UserInfoViewModel source);
[MapperIgnoreTarget(nameof(IdentityUserUpdateDto.RoleNames))]
public override partial void Map(EditUserModalModel.UserInfoViewModel source, IdentityUserUpdateDto destination);
}
[Mapper]
public partial class IdentityRoleDtoToEditUserModalModelAssignedRoleViewModelMapper : MapperBase<IdentityRoleDto, EditUserModalModel.AssignedRoleViewModel>
{
[MapperIgnoreTarget(nameof(EditUserModalModel.AssignedRoleViewModel.IsAssigned))]
public override partial EditUserModalModel.AssignedRoleViewModel Map(IdentityRoleDto source);
[MapperIgnoreTarget(nameof(EditUserModalModel.AssignedRoleViewModel.IsAssigned))]
public override partial void Map(IdentityRoleDto source, EditUserModalModel.AssignedRoleViewModel destination);
}
[Mapper]
public partial class IdentityUserDtoToEditUserModalModelDetailViewModelMapper : MapperBase<IdentityUserDto, EditUserModalModel.DetailViewModel>
{
[MapperIgnoreTarget(nameof(EditUserModalModel.DetailViewModel.CreatedBy))]
[MapperIgnoreTarget(nameof(EditUserModalModel.DetailViewModel.ModifiedBy))]
public override partial EditUserModalModel.DetailViewModel Map(IdentityUserDto source);
[MapperIgnoreTarget(nameof(EditUserModalModel.DetailViewModel.CreatedBy))]
[MapperIgnoreTarget(nameof(EditUserModalModel.DetailViewModel.ModifiedBy))]
public override partial void Map(IdentityUserDto source, EditUserModalModel.DetailViewModel destination);
}
[Mapper]
public partial class IdentityRoleDtoToEditModalModelRoleInfoModelMapper : MapperBase<IdentityRoleDto, EditModalModel.RoleInfoModel>
{
public override partial EditModalModel.RoleInfoModel Map(IdentityRoleDto source);
public override partial void Map(IdentityRoleDto source, EditModalModel.RoleInfoModel destination);
}
[Mapper]
[MapExtraProperties]
public partial class CreateModalModelRoleInfoModelToIdentityRoleCreateDtoMapper : MapperBase<CreateModalModel.RoleInfoModel, IdentityRoleCreateDto>
{
public override partial IdentityRoleCreateDto Map(CreateModalModel.RoleInfoModel source);
public override partial void Map(CreateModalModel.RoleInfoModel source, IdentityRoleCreateDto destination);
}
[Mapper]
[MapExtraProperties]
public partial class EditModalModelRoleInfoModelToIdentityRoleUpdateDtoMapper : MapperBase<EditModalModel.RoleInfoModel, IdentityRoleUpdateDto>
{
public override partial IdentityRoleUpdateDto Map(EditModalModel.RoleInfoModel source);
public override partial void Map(EditModalModel.RoleInfoModel source, IdentityRoleUpdateDto destination);
}

11
modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs

@ -3,7 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars;
using Volo.Abp.AutoMapper;
using Volo.Abp.Mapperly;
using Volo.Abp.Http.ProxyScripting.Generators.JQuery;
using Volo.Abp.Identity.Localization;
using Volo.Abp.Identity.Web.Navigation;
@ -19,7 +19,7 @@ using Volo.Abp.Threading;
namespace Volo.Abp.Identity.Web;
[DependsOn(typeof(AbpIdentityApplicationContractsModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
[DependsOn(typeof(AbpMapperlyModule))]
[DependsOn(typeof(AbpPermissionManagementWebModule))]
[DependsOn(typeof(AbpAspNetCoreMvcUiThemeSharedModule))]
public class AbpIdentityWebModule : AbpModule
@ -51,12 +51,7 @@ public class AbpIdentityWebModule : AbpModule
options.FileSets.AddEmbedded<AbpIdentityWebModule>();
});
context.Services.AddAutoMapperObjectMapper<AbpIdentityWebModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpIdentityWebAutoMapperProfile>(validate: true);
});
context.Services.AddMapperlyObjectMapper<AbpIdentityWebModule>();
Configure<RazorPagesOptions>(options =>
{

2
modules/identity/src/Volo.Abp.Identity.Web/Volo.Abp.Identity.Web.csproj

@ -40,7 +40,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Identity.Application.Contracts\Volo.Abp.Identity.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\permission-management\src\Volo.Abp.PermissionManagement.Web\Volo.Abp.PermissionManagement.Web.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Mapperly\Volo.Abp.Mapperly.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" />
</ItemGroup>

6
npm/ng-packs/packages/core/src/lib/abstracts/auth.guard.ts

@ -21,3 +21,9 @@ export const authGuard: CanActivateFn = () => {
console.error('You should add @abp/ng-oauth packages or create your own auth packages.');
return false;
};
export const asyncAuthGuard: CanActivateFn = () => {
console.error('You should add @abp/ng-oauth packages or create your own auth packages.');
return false;
};

10
npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts

@ -1,4 +1,4 @@
import { makeEnvironmentProviders, Provider, inject, provideAppInitializer } from '@angular/core';
import { makeEnvironmentProviders, Provider, provideAppInitializer, inject } from '@angular/core';
import { TitleStrategy } from '@angular/router';
import {
HTTP_INTERCEPTORS,
@ -23,7 +23,7 @@ import { ABP, SortableItem } from '../models';
import { AuthErrorFilterService } from '../abstracts';
import { DEFAULT_DYNAMIC_LAYOUTS } from '../constants';
import { LocalizationService, LocalStorageListenerService, AbpTitleStrategy } from '../services';
import { DefaultQueueManager, getInitialData, localeInitializer } from '../utils';
import { DefaultQueueManager, getInitialData } from '../utils';
import { CookieLanguageProvider, IncludeLocalizationResourcesProvider, LocaleProvider } from './';
import { TimezoneInterceptor } from '../interceptors';
@ -106,14 +106,12 @@ export function provideAbpCore(...features: CoreFeature<CoreFeatureKind>[]) {
headerName: 'RequestVerificationToken',
}),
),
provideAppInitializer(() => {
getInitialData();
localeInitializer();
provideAppInitializer(async () => {
inject(LocalizationService);
inject(LocalStorageListenerService);
inject(RoutesHandler);
await getInitialData();
}),
LocaleProvider,
CookieLanguageProvider,
{

9
npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts

@ -50,12 +50,13 @@ export async function getInitialData() {
}),
);
await lastValueFrom(result$);
await localeInitializer(injector);
}
export function localeInitializer() {
const injector = inject(Injector);
const sessionState = injector.get(SessionStateService);
const { registerLocaleFn }: ABP.Root = injector.get(CORE_OPTIONS);
export function localeInitializer(injector?: Injector) {
const currentInjector = injector || inject(Injector);
const sessionState = currentInjector.get(SessionStateService);
const { registerLocaleFn }: ABP.Root = currentInjector.get(CORE_OPTIONS);
const lang = sessionState.getLanguage() || 'en';

37
npm/ng-packs/packages/oauth/src/lib/guards/oauth.guard.ts

@ -6,10 +6,10 @@ import {
CanActivateFn,
} from '@angular/router';
import { Observable } from 'rxjs';
import { Observable, timer, filter, take, map, firstValueFrom, timeout, catchError, of } from 'rxjs';
import { OAuthService } from 'angular-oauth2-oidc';
import { AuthService, IAbpGuard } from '@abp/ng.core';
import { AuthService, IAbpGuard, EnvironmentService } from '@abp/ng.core';
/**
* @deprecated Use `abpOAuthGuard` *function* instead.
@ -53,3 +53,36 @@ export const abpOAuthGuard: CanActivateFn = (
authService.navigateToLogin(params);
return false;
};
export const asyncAbpOAuthGuard: CanActivateFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
) => {
const oAuthService = inject(OAuthService);
const authService = inject(AuthService);
const environmentService = inject(EnvironmentService);
const { oAuthConfig } = environmentService.getEnvironment();
if (oAuthConfig?.responseType === 'code') {
return firstValueFrom(
timer(0, 100).pipe(
map(() => oAuthService.hasValidAccessToken()),
filter(Boolean),
take(1),
timeout(3000),
catchError(() => {
authService.navigateToLogin({ returnUrl: state.url });
return of(false);
})
)
);
}
if (oAuthService.hasValidAccessToken()) {
return true;
}
authService.navigateToLogin({ returnUrl: state.url });
return false;
};

7
npm/ng-packs/packages/oauth/src/lib/providers/oauth-module-config.provider.ts

@ -2,6 +2,7 @@ import {
AuthService,
AuthGuard,
authGuard,
asyncAuthGuard,
ApiInterceptor,
PIPE_TO_LOGIN_FN_KEY,
CHECK_AUTHENTICATION_STATE_FN_KEY,
@ -11,7 +12,7 @@ import {
import { Provider, makeEnvironmentProviders, inject, provideAppInitializer } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
import { AbpOAuthGuard, abpOAuthGuard } from '../guards';
import { AbpOAuthGuard, abpOAuthGuard, asyncAbpOAuthGuard, } from '../guards';
import { OAuthConfigurationHandler } from '../handlers';
import { OAuthApiInterceptor } from '../interceptors';
import { AbpOAuthService, OAuthErrorFilterService } from '../services';
@ -31,6 +32,10 @@ export function provideAbpOAuth() {
{
provide: authGuard,
useValue: abpOAuthGuard,
},
{
provide: asyncAuthGuard,
useValue: asyncAbpOAuthGuard,
},
{
provide: ApiInterceptor,

Loading…
Cancel
Save