Browse Source
* add permission defined interface. * add feature defined interface. * refactor persistence localization contributorpull/811/head
136 changed files with 3702 additions and 226 deletions
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,23 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<None Remove="LINGYUN\Abp\FeatureManagement\Localization\Application\Contracts\*.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="LINGYUN\Abp\FeatureManagement\Localization\Application\Contracts\*.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.FeatureManagement.Application.Contracts" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,33 @@ |
|||
using Volo.Abp.FeatureManagement.Localization; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Localization.ExceptionHandling; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
using VoloAbpFeatureManagementApplicationContractsModule = Volo.Abp.FeatureManagement.AbpFeatureManagementApplicationContractsModule; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement; |
|||
|
|||
[DependsOn( |
|||
typeof(VoloAbpFeatureManagementApplicationContractsModule))] |
|||
public class AbpFeatureManagementApplicationContractsModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpFeatureManagementApplicationContractsModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Get<AbpFeatureManagementResource>() |
|||
.AddVirtualJson("/LINGYUN/Abp/FeatureManagement/Localization/Application/Contracts"); |
|||
}); |
|||
|
|||
Configure<AbpExceptionLocalizationOptions>(options => |
|||
{ |
|||
options.MapCodeNamespace(FeatureManagementErrorCodes.Namespace, typeof(AbpFeatureManagementResource)); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
public class FeatureDefinitionCreateDto : FeatureDefinitionCreateOrUpdateDto |
|||
{ |
|||
[Required] |
|||
[DynamicStringLength(typeof(FeatureDefinitionRecordConsts), nameof(FeatureDefinitionRecordConsts.MaxNameLength))] |
|||
public string Name { get; set; } |
|||
|
|||
[Required] |
|||
[DynamicStringLength(typeof(FeatureGroupDefinitionRecordConsts), nameof(FeatureGroupDefinitionRecordConsts.MaxNameLength))] |
|||
public string GroupName { get; set; } |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
public abstract class FeatureDefinitionCreateOrUpdateDto : IHasExtraProperties |
|||
{ |
|||
[Required] |
|||
[DynamicStringLength(typeof(FeatureDefinitionRecordConsts), nameof(FeatureDefinitionRecordConsts.MaxDisplayNameLength))] |
|||
public string DisplayName { get; set; } |
|||
|
|||
[DynamicStringLength(typeof(FeatureDefinitionRecordConsts), nameof(FeatureDefinitionRecordConsts.MaxNameLength))] |
|||
public string ParentName { get; set; } |
|||
|
|||
[DynamicStringLength(typeof(FeatureDefinitionRecordConsts), nameof(FeatureDefinitionRecordConsts.MaxDescriptionLength))] |
|||
public string Description { get; set; } |
|||
|
|||
[DynamicStringLength(typeof(FeatureDefinitionRecordConsts), nameof(FeatureDefinitionRecordConsts.MaxDefaultValueLength))] |
|||
public string DefaultValue { get; set; } |
|||
|
|||
public bool IsVisibleToClients { get; set; } |
|||
|
|||
public bool IsAvailableToHost { get; set; } |
|||
|
|||
public List<string> AllowedProviders { get; set; } = new List<string>(); |
|||
|
|||
[DynamicStringLength(typeof(FeatureDefinitionRecordConsts), nameof(FeatureDefinitionRecordConsts.MaxValueTypeLength))] |
|||
public string ValueType { get; set; } |
|||
|
|||
public ExtraPropertyDictionary ExtraProperties { get; set; } = new ExtraPropertyDictionary(); |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
public class FeatureDefinitionDto : IHasExtraProperties |
|||
{ |
|||
public string GroupName { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public string ParentName { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
|
|||
public string FormatedDisplayName { get; set; } |
|||
|
|||
public string Description { get; set; } |
|||
|
|||
public string FormatedDescription { get; set; } |
|||
|
|||
public string DefaultValue { get; set; } |
|||
|
|||
public bool IsVisibleToClients { get; set; } |
|||
|
|||
public bool IsAvailableToHost { get; set; } |
|||
|
|||
public List<string> AllowedProviders { get; set; } = new List<string>(); |
|||
|
|||
public string ValueType { get; set; } |
|||
|
|||
public ExtraPropertyDictionary ExtraProperties { get; set; } = new ExtraPropertyDictionary(); |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
public class FeatureDefinitionGetListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public string Filter { get; set; } |
|||
|
|||
public string GroupName { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Domain.Entities; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
public class FeatureDefinitionUpdateDto : FeatureDefinitionCreateOrUpdateDto, IHasConcurrencyStamp |
|||
{ |
|||
[StringLength(40)] |
|||
public string ConcurrencyStamp { get; set; } |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
public class FeatureGroupDefinitionCreateDto : FeatureGroupDefinitionCreateOrUpdateDto |
|||
{ |
|||
[Required] |
|||
[DynamicStringLength(typeof(FeatureGroupDefinitionRecordConsts), nameof(FeatureGroupDefinitionRecordConsts.MaxNameLength))] |
|||
public string Name { get; set; } |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
public abstract class FeatureGroupDefinitionCreateOrUpdateDto : IHasExtraProperties |
|||
{ |
|||
[Required] |
|||
[DynamicStringLength(typeof(FeatureGroupDefinitionRecordConsts), nameof(FeatureGroupDefinitionRecordConsts.MaxDisplayNameLength))] |
|||
public string DisplayName { get; set; } |
|||
|
|||
public ExtraPropertyDictionary ExtraProperties { get; set; } = new ExtraPropertyDictionary(); |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
public class FeatureGroupDefinitionDto : IHasExtraProperties |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
|
|||
public string FormatedDisplayName { get; set; } |
|||
|
|||
public ExtraPropertyDictionary ExtraProperties { get; set; } |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
public class FeatureGroupDefinitionGetListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public string Filter { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Domain.Entities; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
public class FeatureGroupDefinitionUpdateDto : FeatureGroupDefinitionCreateOrUpdateDto, IHasConcurrencyStamp |
|||
{ |
|||
[StringLength(40)] |
|||
public string ConcurrencyStamp { get; set; } |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
public interface IFeatureDefinitionAppService : IApplicationService |
|||
{ |
|||
Task<FeatureDefinitionDto> GetAsync(string name); |
|||
|
|||
Task DeleteAsync(string name); |
|||
|
|||
Task<FeatureDefinitionDto> CreateAsync(FeatureDefinitionCreateDto input); |
|||
|
|||
Task<FeatureDefinitionDto> UpdateAsync(string name, FeatureDefinitionUpdateDto input); |
|||
|
|||
Task<PagedResultDto<FeatureDefinitionDto>> GetListAsync(FeatureDefinitionGetListInput input); |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
public interface IFeatureGroupDefinitionAppService : IApplicationService |
|||
{ |
|||
Task<FeatureGroupDefinitionDto> GetAsync(string name); |
|||
|
|||
Task DeleteAsync(string name); |
|||
|
|||
Task<FeatureGroupDefinitionDto> CreateAsync(FeatureGroupDefinitionCreateDto input); |
|||
|
|||
Task<FeatureGroupDefinitionDto> UpdateAsync(string name, FeatureGroupDefinitionUpdateDto input); |
|||
|
|||
Task<PagedResultDto<FeatureGroupDefinitionDto>> GetListAsync(FeatureGroupDefinitionGetListInput input); |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
namespace LINGYUN.Abp.FeatureManagement; |
|||
public static class FeatureManagementErrorCodes |
|||
{ |
|||
public const string Namespace = "FeatureManagement"; |
|||
|
|||
public static class GroupDefinition |
|||
{ |
|||
private const string Prefix = Namespace + ":001"; |
|||
|
|||
public const string AlreayNameExists = Prefix + "100"; |
|||
|
|||
public const string NameNotFount = Prefix + "404"; |
|||
} |
|||
|
|||
public static class Definition |
|||
{ |
|||
private const string Prefix = Namespace + ":002"; |
|||
|
|||
public const string AlreayNameExists = Prefix + "100"; |
|||
|
|||
public const string FailedGetGroup = Prefix + "101"; |
|||
|
|||
public const string NameNotFount = Prefix + "404"; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
{ |
|||
"culture": "en", |
|||
"texts": { |
|||
"Permission:FeatureManagement": "Feature Management", |
|||
"Permission:GroupDefinitions": "Group Definitions", |
|||
"Permission:FeatureDefinitions": "Permission Definitions", |
|||
"Permission:Create": "Create", |
|||
"Permission:Edit": "Edit", |
|||
"Permission:Delete": "Delete", |
|||
"FeatureManagement:001100": "Feature group {Name} already exists!", |
|||
"FeatureManagement:001404": "Feature group named {Name} not found!", |
|||
"FeatureManagement:002100": "Feature {Name} already exists!", |
|||
"FeatureManagement:002101": "The group definition of feature {Name} could not be retrieved!", |
|||
"FeatureManagement:0021404": "Feature named {Name} not found!" |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
{ |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"Permission:GroupDefinitions": "分组定义", |
|||
"Permission:FeatureDefinitions": "功能定义", |
|||
"Permission:Create": "新增", |
|||
"Permission:Edit": "修改", |
|||
"Permission:Delete": "删除", |
|||
"FeatureManagement:001100": "功能分组 {Name} 已经存在!", |
|||
"FeatureManagement:001404": "没有找到名为 {Name} 的功能分组!", |
|||
"FeatureManagement:002100": "功能 {Name} 已经存在!", |
|||
"FeatureManagement:002101": "未能检索到功能 {Name} 所在分组定义!", |
|||
"FeatureManagement:0021404": "没有找到名为 {Name} 的功能定义!" |
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.FeatureManagement.Localization; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Permissions; |
|||
|
|||
public class FeatureManagementPermissionDefinitionProvider : PermissionDefinitionProvider |
|||
{ |
|||
public override void Define(IPermissionDefinitionContext context) |
|||
{ |
|||
var featureGroup = context.GetGroup(FeatureManagementPermissionNames.GroupName); |
|||
|
|||
var groupDefinition = featureGroup.AddPermission( |
|||
FeatureManagementPermissionNames.GroupDefinition.Default, |
|||
L("Permission:GroupDefinitions"), |
|||
MultiTenancySides.Host); |
|||
groupDefinition.AddChild( |
|||
FeatureManagementPermissionNames.GroupDefinition.Create, |
|||
L("Permission:Create"), |
|||
MultiTenancySides.Host); |
|||
groupDefinition.AddChild( |
|||
FeatureManagementPermissionNames.GroupDefinition.Update, |
|||
L("Permission:Edit"), |
|||
MultiTenancySides.Host); |
|||
groupDefinition.AddChild( |
|||
FeatureManagementPermissionNames.GroupDefinition.Delete, |
|||
L("Permission:Delete"), |
|||
MultiTenancySides.Host); |
|||
|
|||
var featureDefinition = featureGroup.AddPermission( |
|||
FeatureManagementPermissionNames.Definition.Default, |
|||
L("Permission:FeatureDefinitions"), |
|||
MultiTenancySides.Host); |
|||
featureDefinition.AddChild( |
|||
FeatureManagementPermissionNames.Definition.Create, |
|||
L("Permission:Create"), |
|||
MultiTenancySides.Host); |
|||
featureDefinition.AddChild( |
|||
FeatureManagementPermissionNames.Definition.Update, |
|||
L("Permission:Edit"), |
|||
MultiTenancySides.Host); |
|||
featureDefinition.AddChild( |
|||
FeatureManagementPermissionNames.Definition.Delete, |
|||
L("Permission:Delete"), |
|||
MultiTenancySides.Host); |
|||
} |
|||
|
|||
private static LocalizableString L(string name) |
|||
{ |
|||
return LocalizableString.Create<AbpFeatureManagementResource>(name); |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using Volo.Abp.FeatureManagement; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Permissions; |
|||
public static class FeatureManagementPermissionNames |
|||
{ |
|||
public const string GroupName = FeatureManagementPermissions.GroupName; |
|||
|
|||
public static class GroupDefinition |
|||
{ |
|||
public const string Default = GroupName + ".GroupDefinitions"; |
|||
|
|||
public const string Create = Default + ".Create"; |
|||
public const string Update = Default + ".Update"; |
|||
public const string Delete = Default + ".Delete"; |
|||
} |
|||
|
|||
public static class Definition |
|||
{ |
|||
public const string Default = GroupName + ".Definitions"; |
|||
|
|||
public const string Create = Default + ".Create"; |
|||
public const string Update = Default + ".Update"; |
|||
public const string Delete = Default + ".Delete"; |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.FeatureManagement.Application" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.FeatureManagement.Application.Contracts\LINGYUN.Abp.FeatureManagement.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,11 @@ |
|||
using Volo.Abp.Modularity; |
|||
using VoloAbpFeatureManagementApplicationModule = Volo.Abp.FeatureManagement.AbpFeatureManagementApplicationModule; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementApplicationContractsModule), |
|||
typeof(VoloAbpFeatureManagementApplicationModule))] |
|||
public class AbpFeatureManagementApplicationModule : AbpModule |
|||
{ |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Entities.Events; |
|||
using Volo.Abp.EventBus; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Threading; |
|||
using Volo.Abp.Timing; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
public class DynamicPermissionDefinitionStoreCacheInvalidator : |
|||
ILocalEventHandler<EntityChangedEventData<FeatureGroupDefinitionRecord>>, |
|||
ILocalEventHandler<EntityChangedEventData<FeatureDefinitionRecord>>, |
|||
ITransientDependency |
|||
{ |
|||
private readonly IDynamicFeatureDefinitionStoreInMemoryCache _storeCache; |
|||
|
|||
private readonly IClock _clock; |
|||
private readonly IDistributedCache _distributedCache; |
|||
private readonly AbpDistributedCacheOptions _cacheOptions; |
|||
|
|||
public DynamicPermissionDefinitionStoreCacheInvalidator( |
|||
IClock clock, |
|||
IDistributedCache distributedCache, |
|||
IDynamicFeatureDefinitionStoreInMemoryCache storeCache, |
|||
IOptions<AbpDistributedCacheOptions> cacheOptions) |
|||
{ |
|||
_storeCache = storeCache; |
|||
_clock = clock; |
|||
_distributedCache = distributedCache; |
|||
_cacheOptions = cacheOptions.Value; |
|||
} |
|||
|
|||
public async virtual Task HandleEventAsync(EntityChangedEventData<FeatureGroupDefinitionRecord> eventData) |
|||
{ |
|||
await RemoveStampInDistributedCacheAsync(); |
|||
} |
|||
|
|||
public async virtual Task HandleEventAsync(EntityChangedEventData<FeatureDefinitionRecord> eventData) |
|||
{ |
|||
await RemoveStampInDistributedCacheAsync(); |
|||
} |
|||
|
|||
protected async virtual Task RemoveStampInDistributedCacheAsync() |
|||
{ |
|||
using (await _storeCache.SyncSemaphore.LockAsync()) |
|||
{ |
|||
var cacheKey = GetCommonStampCacheKey(); |
|||
|
|||
await _distributedCache.RemoveAsync(cacheKey); |
|||
|
|||
_storeCache.CacheStamp = Guid.NewGuid().ToString(); |
|||
_storeCache.LastCheckTime = _clock.Now.AddMinutes(-5); |
|||
} |
|||
} |
|||
|
|||
protected virtual string GetCommonStampCacheKey() |
|||
{ |
|||
return $"{_cacheOptions.KeyPrefix}_AbpInMemoryFeatureCacheStamp"; |
|||
} |
|||
} |
|||
@ -0,0 +1,334 @@ |
|||
using LINGYUN.Abp.FeatureManagement.Permissions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.Extensions.Localization; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
[Authorize(FeatureManagementPermissionNames.Definition.Default)] |
|||
public class FeatureDefinitionAppService : FeatureManagementAppServiceBase, IFeatureDefinitionAppService |
|||
{ |
|||
private readonly ILocalizableStringSerializer _localizableStringSerializer; |
|||
private readonly IFeatureDefinitionManager _featureDefinitionManager; |
|||
|
|||
private readonly IFeatureDefinitionRecordRepository _definitionRepository; |
|||
private readonly IRepository<FeatureDefinitionRecord, Guid> _definitionBasicRepository; |
|||
|
|||
public FeatureDefinitionAppService( |
|||
ILocalizableStringSerializer localizableStringSerializer, |
|||
IFeatureDefinitionManager featureDefinitionManager, |
|||
IFeatureDefinitionRecordRepository definitionRepository, |
|||
IRepository<FeatureDefinitionRecord, Guid> definitionBasicRepository) |
|||
{ |
|||
_localizableStringSerializer = localizableStringSerializer; |
|||
_featureDefinitionManager = featureDefinitionManager; |
|||
_definitionRepository = definitionRepository; |
|||
_definitionBasicRepository = definitionBasicRepository; |
|||
} |
|||
|
|||
[Authorize(FeatureManagementPermissionNames.Definition.Create)] |
|||
public async virtual Task<FeatureDefinitionDto> CreateAsync(FeatureDefinitionCreateDto input) |
|||
{ |
|||
if (await _featureDefinitionManager.GetOrNullAsync(input.Name) != null) |
|||
{ |
|||
throw new BusinessException(FeatureManagementErrorCodes.Definition.AlreayNameExists) |
|||
.WithData(nameof(FeatureDefinitionRecord.Name), input.Name); |
|||
} |
|||
|
|||
var groupDefinition = await _featureDefinitionManager.GetGroupOrNullAsync(input.GroupName); |
|||
if (groupDefinition == null) |
|||
{ |
|||
throw new BusinessException(FeatureManagementErrorCodes.GroupDefinition.NameNotFount) |
|||
.WithData(nameof(FeatureGroupDefinitionRecord.Name), input.GroupName); |
|||
} |
|||
|
|||
var definitionRecord = new FeatureDefinitionRecord( |
|||
GuidGenerator.Create(), |
|||
groupDefinition.Name, |
|||
input.Name, |
|||
input.ParentName, |
|||
input.DisplayName, |
|||
input.Description, |
|||
input.DefaultValue, |
|||
input.IsVisibleToClients, |
|||
input.IsAvailableToHost, |
|||
valueType: input.ValueType); |
|||
|
|||
if (input.AllowedProviders.Any()) |
|||
{ |
|||
definitionRecord.AllowedProviders = input.AllowedProviders.JoinAsString(","); |
|||
} |
|||
|
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
definitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
await _definitionRepository.InsertAsync(definitionRecord); |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
|
|||
var dto = await DefinitionRecordToDto(definitionRecord); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
[Authorize(FeatureManagementPermissionNames.Definition.Delete)] |
|||
public async virtual Task DeleteAsync(string name) |
|||
{ |
|||
var definitionRecord = await FindByNameAsync(name); |
|||
|
|||
if (definitionRecord == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await _definitionRepository.DeleteAsync(definitionRecord); |
|||
} |
|||
|
|||
public async virtual Task<FeatureDefinitionDto> GetAsync(string name) |
|||
{ |
|||
var definition = await _featureDefinitionManager.GetOrNullAsync(name); |
|||
if (definition == null) |
|||
{ |
|||
throw new BusinessException(FeatureManagementErrorCodes.Definition.NameNotFount) |
|||
.WithData(nameof(FeatureDefinitionRecord.Name), name); |
|||
} |
|||
|
|||
var groupDefinition = await GetGroupDefinition(definition); |
|||
|
|||
var dto = await DefinitionToDto(groupDefinition, definition); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
public async virtual Task<PagedResultDto<FeatureDefinitionDto>> GetListAsync(FeatureDefinitionGetListInput input) |
|||
{ |
|||
var permissions = new List<FeatureDefinitionDto>(); |
|||
|
|||
IReadOnlyList<FeatureDefinition> definitionPermissions; |
|||
|
|||
if (!input.GroupName.IsNullOrWhiteSpace()) |
|||
{ |
|||
var group = await _featureDefinitionManager.GetGroupOrNullAsync(input.GroupName); |
|||
if (group == null) |
|||
{ |
|||
return new PagedResultDto<FeatureDefinitionDto>(0, permissions); |
|||
} |
|||
|
|||
definitionPermissions = group.GetFeaturesWithChildren(); |
|||
} |
|||
else |
|||
{ |
|||
definitionPermissions = await _featureDefinitionManager.GetAllAsync(); |
|||
} |
|||
|
|||
var definitionFilter = definitionPermissions.AsQueryable() |
|||
.WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => x.Name.Contains(input.Filter) || |
|||
(x.Parent != null && x.Parent.Name.Contains(input.Filter))); |
|||
|
|||
var sorting = input.Sorting; |
|||
if (sorting.IsNullOrWhiteSpace()) |
|||
{ |
|||
sorting = nameof(FeatureDefinitionRecord.Name); |
|||
} |
|||
|
|||
var filterDefinitionCount = definitionFilter.Count(); |
|||
var filterDefinitions = definitionFilter |
|||
.OrderBy(sorting) |
|||
.PageBy(input.SkipCount, input.MaxResultCount); |
|||
|
|||
foreach (var definition in filterDefinitions) |
|||
{ |
|||
var groupDefinition = await GetGroupDefinition(definition); |
|||
var Dto = await DefinitionToDto(groupDefinition, definition); |
|||
|
|||
permissions.Add(Dto); |
|||
} |
|||
|
|||
return new PagedResultDto<FeatureDefinitionDto>(filterDefinitionCount, permissions); |
|||
} |
|||
|
|||
[Authorize(FeatureManagementPermissionNames.Definition.Update)] |
|||
public async virtual Task<FeatureDefinitionDto> UpdateAsync(string name, FeatureDefinitionUpdateDto input) |
|||
{ |
|||
var definition = await _featureDefinitionManager.GetAsync(name); |
|||
var definitionRecord = await FindByNameAsync(name); |
|||
|
|||
if (definitionRecord == null) |
|||
{ |
|||
var groupDefinition = await GetGroupDefinition(definition); |
|||
definitionRecord = new FeatureDefinitionRecord( |
|||
GuidGenerator.Create(), |
|||
groupDefinition.Name, |
|||
name, |
|||
input.ParentName, |
|||
input.DisplayName, |
|||
input.Description, |
|||
input.DefaultValue, |
|||
input.IsVisibleToClients, |
|||
input.IsAvailableToHost, |
|||
valueType: input.ValueType); |
|||
|
|||
if (input.AllowedProviders.Any()) |
|||
{ |
|||
definitionRecord.AllowedProviders = input.AllowedProviders.JoinAsString(","); |
|||
} |
|||
|
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
definitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
definitionRecord = await _definitionBasicRepository.InsertAsync(definitionRecord); |
|||
} |
|||
else |
|||
{ |
|||
definitionRecord.ExtraProperties.Clear(); |
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
definitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
if (input.AllowedProviders.Any()) |
|||
{ |
|||
definitionRecord.AllowedProviders = input.AllowedProviders.JoinAsString(","); |
|||
} |
|||
|
|||
if (!string.Equals(definitionRecord.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase)) |
|||
{ |
|||
definitionRecord.DisplayName = input.DisplayName; |
|||
} |
|||
|
|||
if (!string.Equals(definitionRecord.Description, input.Description, StringComparison.InvariantCultureIgnoreCase)) |
|||
{ |
|||
definitionRecord.Description = input.Description; |
|||
} |
|||
|
|||
if (!string.Equals(definitionRecord.DefaultValue, input.DefaultValue, StringComparison.InvariantCultureIgnoreCase)) |
|||
{ |
|||
definitionRecord.DefaultValue = input.DefaultValue; |
|||
} |
|||
|
|||
if (!string.Equals(definitionRecord.ValueType, input.ValueType, StringComparison.InvariantCultureIgnoreCase)) |
|||
{ |
|||
definitionRecord.ValueType = input.ValueType; |
|||
} |
|||
|
|||
definitionRecord.IsAvailableToHost = input.IsAvailableToHost; |
|||
definitionRecord.IsVisibleToClients = input.IsVisibleToClients; |
|||
|
|||
definitionRecord = await _definitionBasicRepository.UpdateAsync(definitionRecord); |
|||
} |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
|
|||
var dto = await DefinitionRecordToDto(definitionRecord); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
protected async virtual Task<FeatureDefinitionRecord> FindByNameAsync(string name) |
|||
{ |
|||
var DefinitionFilter = await _definitionBasicRepository.GetQueryableAsync(); |
|||
|
|||
var definitionRecord = await AsyncExecuter.FirstOrDefaultAsync( |
|||
DefinitionFilter.Where(x => x.Name == name)); |
|||
|
|||
return definitionRecord; |
|||
} |
|||
|
|||
protected async virtual Task<FeatureGroupDefinition> GetGroupDefinition(FeatureDefinition definition) |
|||
{ |
|||
var groups = await _featureDefinitionManager.GetGroupsAsync(); |
|||
|
|||
foreach (var group in groups) |
|||
{ |
|||
if (group.GetFeatureOrNull(definition.Name) != null) |
|||
{ |
|||
return group; |
|||
} |
|||
} |
|||
|
|||
throw new BusinessException(FeatureManagementErrorCodes.Definition.FailedGetGroup) |
|||
.WithData(nameof(FeatureDefinitionRecord.Name), definition.Name); |
|||
} |
|||
|
|||
protected async virtual Task<FeatureDefinitionDto> DefinitionRecordToDto(FeatureDefinitionRecord definitionRecord) |
|||
{ |
|||
var dto = new FeatureDefinitionDto |
|||
{ |
|||
Name = definitionRecord.Name, |
|||
GroupName = definitionRecord.GroupName, |
|||
ParentName = definitionRecord.ParentName, |
|||
IsAvailableToHost = definitionRecord.IsAvailableToHost, |
|||
IsVisibleToClients = definitionRecord.IsVisibleToClients, |
|||
DefaultValue = definitionRecord.DefaultValue, |
|||
ValueType = definitionRecord.ValueType, |
|||
AllowedProviders = definitionRecord.AllowedProviders.Split(',').ToList(), |
|||
FormatedDescription = definitionRecord.Description, |
|||
FormatedDisplayName = definitionRecord.DisplayName, |
|||
}; |
|||
|
|||
var displayName = _localizableStringSerializer.Deserialize(definitionRecord.DisplayName); |
|||
dto.DisplayName = await displayName.LocalizeAsync(StringLocalizerFactory); |
|||
|
|||
if (!definitionRecord.Description.IsNullOrWhiteSpace()) |
|||
{ |
|||
var description = _localizableStringSerializer.Deserialize(definitionRecord.Description); |
|||
dto.Description = await description.LocalizeAsync(StringLocalizerFactory); |
|||
} |
|||
|
|||
foreach (var property in definitionRecord.ExtraProperties) |
|||
{ |
|||
dto.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
protected async virtual Task<FeatureDefinitionDto> DefinitionToDto(FeatureGroupDefinition groupDefinition, FeatureDefinition definition) |
|||
{ |
|||
var dto = new FeatureDefinitionDto |
|||
{ |
|||
Name = definition.Name, |
|||
GroupName = groupDefinition.Name, |
|||
ParentName = definition.Parent?.Name, |
|||
DefaultValue = definition.DefaultValue, |
|||
AllowedProviders = definition.AllowedProviders, |
|||
IsAvailableToHost = definition.IsAvailableToHost, |
|||
IsVisibleToClients = definition.IsVisibleToClients, |
|||
ValueType = definition.ValueType.Name, |
|||
}; |
|||
|
|||
if (definition.DisplayName != null) |
|||
{ |
|||
dto.DisplayName = await definition.DisplayName.LocalizeAsync(StringLocalizerFactory); |
|||
dto.FormatedDisplayName = _localizableStringSerializer.Serialize(definition.DisplayName); |
|||
} |
|||
|
|||
if (definition.Description != null) |
|||
{ |
|||
dto.Description = await definition.Description.LocalizeAsync(StringLocalizerFactory); |
|||
dto.FormatedDescription = _localizableStringSerializer.Serialize(definition.Description); |
|||
} |
|||
|
|||
foreach (var property in definition.Properties) |
|||
{ |
|||
dto.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
return dto; |
|||
} |
|||
} |
|||
@ -0,0 +1,215 @@ |
|||
using LINGYUN.Abp.FeatureManagement.Permissions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.Definitions; |
|||
|
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Default)] |
|||
public class FeatureGroupDefinitionAppService : FeatureManagementAppServiceBase, IFeatureGroupDefinitionAppService |
|||
{ |
|||
private readonly ILocalizableStringSerializer _localizableStringSerializer; |
|||
private readonly IFeatureDefinitionManager _featureDefinitionManager; |
|||
|
|||
private readonly IFeatureGroupDefinitionRecordRepository _groupDefinitionRepository; |
|||
private readonly IRepository<FeatureGroupDefinitionRecord, Guid> _groupDefinitionBasicRepository; |
|||
|
|||
public FeatureGroupDefinitionAppService( |
|||
ILocalizableStringSerializer localizableStringSerializer, |
|||
IFeatureDefinitionManager featureDefinitionManager, |
|||
IFeatureGroupDefinitionRecordRepository groupDefinitionRepository, |
|||
IRepository<FeatureGroupDefinitionRecord, Guid> groupDefinitionBasicRepository) |
|||
{ |
|||
_localizableStringSerializer = localizableStringSerializer; |
|||
_featureDefinitionManager = featureDefinitionManager; |
|||
_groupDefinitionRepository = groupDefinitionRepository; |
|||
_groupDefinitionBasicRepository = groupDefinitionBasicRepository; |
|||
} |
|||
|
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Create)] |
|||
public async virtual Task<FeatureGroupDefinitionDto> CreateAsync(FeatureGroupDefinitionCreateDto input) |
|||
{ |
|||
if (await _featureDefinitionManager.GetGroupOrNullAsync(input.Name) != null) |
|||
{ |
|||
throw new BusinessException(FeatureManagementErrorCodes.GroupDefinition.AlreayNameExists) |
|||
.WithData(nameof(FeatureGroupDefinitionRecord.Name), input.Name); |
|||
} |
|||
|
|||
var groupDefinitionRecord = new FeatureGroupDefinitionRecord( |
|||
GuidGenerator.Create(), |
|||
input.Name, |
|||
input.DisplayName); |
|||
|
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
groupDefinitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
await _groupDefinitionRepository.InsertAsync(groupDefinitionRecord); |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
|
|||
var dto = await GroupDefinitionRecordToDto(groupDefinitionRecord); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Delete)] |
|||
public async virtual Task DeleteAsync(string name) |
|||
{ |
|||
var groupDefinitionRecord = await FindByNameAsync(name); |
|||
|
|||
if (groupDefinitionRecord == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await _groupDefinitionRepository.DeleteAsync(groupDefinitionRecord); |
|||
} |
|||
|
|||
public async virtual Task<FeatureGroupDefinitionDto> GetAsync(string name) |
|||
{ |
|||
var groupDefinition = await _featureDefinitionManager.GetGroupOrNullAsync(name); |
|||
if (groupDefinition == null) |
|||
{ |
|||
throw new BusinessException(FeatureManagementErrorCodes.GroupDefinition.NameNotFount) |
|||
.WithData(nameof(FeatureGroupDefinitionRecord.Name), name); |
|||
} |
|||
|
|||
var dto = await GroupDefinitionToDto(groupDefinition); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
public async virtual Task<PagedResultDto<FeatureGroupDefinitionDto>> GetListAsync(FeatureGroupDefinitionGetListInput input) |
|||
{ |
|||
var groups = new List<FeatureGroupDefinitionDto>(); |
|||
|
|||
var groupDefinitions = await _featureDefinitionManager.GetGroupsAsync(); |
|||
|
|||
var groupDefinitionFilter = groupDefinitions.AsQueryable() |
|||
.WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => x.Name.Contains(input.Filter)); |
|||
|
|||
var sorting = input.Sorting; |
|||
if (sorting.IsNullOrWhiteSpace()) |
|||
{ |
|||
sorting = nameof(FeatureDefinitionRecord.Name); |
|||
} |
|||
|
|||
var filterGroupDefinitionCount = groupDefinitionFilter.Count(); |
|||
var filterGroupDefinitions = groupDefinitionFilter |
|||
.OrderBy(sorting) |
|||
.PageBy(input.SkipCount, input.MaxResultCount); |
|||
|
|||
foreach (var groupDefinition in filterGroupDefinitions) |
|||
{ |
|||
var groupDto = await GroupDefinitionToDto(groupDefinition); |
|||
|
|||
groups.Add(groupDto); |
|||
} |
|||
|
|||
return new PagedResultDto<FeatureGroupDefinitionDto>(filterGroupDefinitionCount, groups); |
|||
} |
|||
|
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Update)] |
|||
public async virtual Task<FeatureGroupDefinitionDto> UpdateAsync(string name, FeatureGroupDefinitionUpdateDto input) |
|||
{ |
|||
var groupDefinitionRecord = await FindByNameAsync(name); |
|||
|
|||
if (groupDefinitionRecord == null) |
|||
{ |
|||
groupDefinitionRecord = new FeatureGroupDefinitionRecord( |
|||
GuidGenerator.Create(), |
|||
name, |
|||
input.DisplayName); |
|||
|
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
groupDefinitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
groupDefinitionRecord = await _groupDefinitionBasicRepository.InsertAsync(groupDefinitionRecord); |
|||
} |
|||
else |
|||
{ |
|||
groupDefinitionRecord.ExtraProperties.Clear(); |
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
groupDefinitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
if (!string.Equals(groupDefinitionRecord.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase)) |
|||
{ |
|||
groupDefinitionRecord.DisplayName = input.DisplayName; |
|||
} |
|||
|
|||
groupDefinitionRecord = await _groupDefinitionBasicRepository.UpdateAsync(groupDefinitionRecord); |
|||
} |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
|
|||
var dto = await GroupDefinitionRecordToDto(groupDefinitionRecord); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
protected async virtual Task<FeatureGroupDefinitionRecord> FindByNameAsync(string name) |
|||
{ |
|||
var groupDefinitionFilter = await _groupDefinitionBasicRepository.GetQueryableAsync(); |
|||
|
|||
var groupDefinitionRecord = await AsyncExecuter.FirstOrDefaultAsync( |
|||
groupDefinitionFilter.Where(x => x.Name == name)); |
|||
|
|||
return groupDefinitionRecord; |
|||
} |
|||
|
|||
protected async virtual Task<FeatureGroupDefinitionDto> GroupDefinitionRecordToDto(FeatureGroupDefinitionRecord groupDefinitionRecord) |
|||
{ |
|||
var groupDto = new FeatureGroupDefinitionDto |
|||
{ |
|||
Name = groupDefinitionRecord.Name, |
|||
FormatedDisplayName = groupDefinitionRecord.DisplayName, |
|||
}; |
|||
|
|||
var displayName = _localizableStringSerializer.Deserialize(groupDefinitionRecord.DisplayName); |
|||
groupDto.DisplayName = await displayName.LocalizeAsync(StringLocalizerFactory); |
|||
|
|||
foreach (var property in groupDefinitionRecord.ExtraProperties) |
|||
{ |
|||
groupDto.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
return groupDto; |
|||
} |
|||
|
|||
protected async virtual Task<FeatureGroupDefinitionDto> GroupDefinitionToDto(FeatureGroupDefinition groupDefinition) |
|||
{ |
|||
var groupDto = new FeatureGroupDefinitionDto |
|||
{ |
|||
Name = groupDefinition.Name |
|||
}; |
|||
|
|||
if (groupDefinition.DisplayName != null) |
|||
{ |
|||
groupDto.DisplayName = await groupDefinition.DisplayName.LocalizeAsync(StringLocalizerFactory); |
|||
groupDto.FormatedDisplayName = _localizableStringSerializer.Serialize(groupDefinition.DisplayName); |
|||
} |
|||
|
|||
foreach (var property in groupDefinition.Properties) |
|||
{ |
|||
groupDto.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
return groupDto; |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using JetBrains.Annotations; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.Features; |
|||
public static class FeatureGroupDefinitionExtensions |
|||
{ |
|||
public static FeatureDefinition GetFeatureOrNull( |
|||
this FeatureGroupDefinition group, |
|||
[NotNull] string name) |
|||
{ |
|||
Check.NotNull(name, nameof(name)); |
|||
|
|||
return GetFeatureOrNullRecursively(group.Features, name); |
|||
} |
|||
|
|||
private static FeatureDefinition GetFeatureOrNullRecursively( |
|||
IReadOnlyList<FeatureDefinition> features, |
|||
string name) |
|||
{ |
|||
foreach (var feature in features) |
|||
{ |
|||
if (feature.Name == name) |
|||
{ |
|||
return feature; |
|||
} |
|||
|
|||
var childFeature = GetFeatureOrNullRecursively(feature.Children, name); |
|||
if (childFeature != null) |
|||
{ |
|||
return childFeature; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Features; |
|||
public static class IPermissionDefinitionManagerExtensions |
|||
{ |
|||
public async static Task<FeatureGroupDefinition> GetGroupOrNullAsync( |
|||
this IFeatureDefinitionManager featureDefinitionManager, |
|||
string name |
|||
) |
|||
{ |
|||
var groups = await featureDefinitionManager.GetGroupsAsync(); |
|||
|
|||
return groups.FirstOrDefault(x => x.Name == name); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.FeatureManagement.HttpApi" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.FeatureManagement.Application.Contracts\LINGYUN.Abp.FeatureManagement.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,28 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Mvc.Localization; |
|||
using Volo.Abp.FeatureManagement.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using VoloAbpFeatureManagementHttpApiModule = Volo.Abp.FeatureManagement.AbpFeatureManagementHttpApiModule; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.HttpApi; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpFeatureManagementApplicationContractsModule), |
|||
typeof(VoloAbpFeatureManagementHttpApiModule))] |
|||
public class AbpFeatureManagementHttpApiModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
PreConfigure(delegate (IMvcBuilder mvcBuilder) |
|||
{ |
|||
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpFeatureManagementHttpApiModule)!.Assembly); |
|||
}); |
|||
|
|||
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
|||
{ |
|||
options.AddAssemblyResource( |
|||
typeof(AbpFeatureManagementResource), |
|||
typeof(AbpFeatureManagementApplicationContractsModule).Assembly); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using LINGYUN.Abp.FeatureManagement.Definitions; |
|||
using LINGYUN.Abp.FeatureManagement.Permissions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.FeatureManagement; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.HttpApi.Definitions; |
|||
|
|||
[Controller] |
|||
[Authorize(FeatureManagementPermissionNames.Definition.Default)] |
|||
[RemoteService(Name = FeatureManagementRemoteServiceConsts.RemoteServiceName)] |
|||
[Area(FeatureManagementRemoteServiceConsts.ModuleName)] |
|||
[Route("api/feature-management/definitions")] |
|||
public class FeatureDefinitionController : FeatureManagementControllerBase, IFeatureDefinitionAppService |
|||
{ |
|||
private readonly IFeatureDefinitionAppService _service; |
|||
|
|||
public FeatureDefinitionController(IFeatureDefinitionAppService service) |
|||
{ |
|||
_service = service; |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Authorize(FeatureManagementPermissionNames.Definition.Create)] |
|||
public virtual Task<FeatureDefinitionDto> CreateAsync(FeatureDefinitionCreateDto input) |
|||
{ |
|||
return _service.CreateAsync(input); |
|||
} |
|||
|
|||
[HttpDelete] |
|||
[Route("{name}")] |
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Delete)] |
|||
public virtual Task DeleteAsync(string name) |
|||
{ |
|||
return _service.DeleteAsync(name); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("{name}")] |
|||
[Authorize(FeatureManagementPermissionNames.Definition.Delete)] |
|||
public virtual Task<FeatureDefinitionDto> GetAsync(string name) |
|||
{ |
|||
return _service.GetAsync(name); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public virtual Task<PagedResultDto<FeatureDefinitionDto>> GetListAsync(FeatureDefinitionGetListInput input) |
|||
{ |
|||
return _service.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("{name}")] |
|||
[Authorize(FeatureManagementPermissionNames.Definition.Update)] |
|||
public virtual Task<FeatureDefinitionDto> UpdateAsync(string name, FeatureDefinitionUpdateDto input) |
|||
{ |
|||
return _service.UpdateAsync(name, input); |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using LINGYUN.Abp.FeatureManagement.Definitions; |
|||
using LINGYUN.Abp.FeatureManagement.Permissions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.FeatureManagement; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.HttpApi.Definitions; |
|||
|
|||
[Controller] |
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Default)] |
|||
[RemoteService(Name = FeatureManagementRemoteServiceConsts.RemoteServiceName)] |
|||
[Area(FeatureManagementRemoteServiceConsts.ModuleName)] |
|||
[Route("api/feature-management/definitions/groups")] |
|||
public class FeatureGroupDefinitionController : FeatureManagementControllerBase, IFeatureGroupDefinitionAppService |
|||
{ |
|||
private readonly IFeatureGroupDefinitionAppService _service; |
|||
|
|||
public FeatureGroupDefinitionController(IFeatureGroupDefinitionAppService service) |
|||
{ |
|||
_service = service; |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Create)] |
|||
public virtual Task<FeatureGroupDefinitionDto> CreateAsync(FeatureGroupDefinitionCreateDto input) |
|||
{ |
|||
return _service.CreateAsync(input); |
|||
} |
|||
|
|||
[HttpDelete] |
|||
[Route("{name}")] |
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Delete)] |
|||
public virtual Task DeleteAsync(string name) |
|||
{ |
|||
return _service.DeleteAsync(name); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("{name}")] |
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Delete)] |
|||
public virtual Task<FeatureGroupDefinitionDto> GetAsync(string name) |
|||
{ |
|||
return _service.GetAsync(name); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public virtual Task<PagedResultDto<FeatureGroupDefinitionDto>> GetListAsync(FeatureGroupDefinitionGetListInput input) |
|||
{ |
|||
return _service.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("{name}")] |
|||
[Authorize(FeatureManagementPermissionNames.GroupDefinition.Update)] |
|||
public virtual Task<FeatureGroupDefinitionDto> UpdateAsync(string name, FeatureGroupDefinitionUpdateDto input) |
|||
{ |
|||
return _service.UpdateAsync(name, input); |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.FeatureManagement.Localization; |
|||
|
|||
namespace LINGYUN.Abp.FeatureManagement.HttpApi; |
|||
|
|||
public abstract class FeatureManagementControllerBase : AbpControllerBase |
|||
{ |
|||
protected FeatureManagementControllerBase() |
|||
{ |
|||
LocalizationResource = typeof(AbpFeatureManagementResource); |
|||
} |
|||
} |
|||
@ -0,0 +1,135 @@ |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace LINGYUN.Abp.Localization.Persistence; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
public class DefaultStaticLocalizationSaver : IStaticLocalizationSaver, ITransientDependency |
|||
{ |
|||
protected ILocalizationPersistenceWriter LocalizationPersistenceWriter { get; } |
|||
|
|||
protected AbpLocalizationOptions LocalizationOptions { get; } |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
protected AbpLocalizationPersistenceOptions LocalizationPersistenceOptions { get; } |
|||
|
|||
public DefaultStaticLocalizationSaver( |
|||
IServiceProvider serviceProvider, |
|||
ILocalizationPersistenceWriter localizationPersistenceWriter, |
|||
IOptions<AbpLocalizationOptions> localizationOptions, |
|||
IOptions<AbpLocalizationPersistenceOptions> localizationPersistenceOptions) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
LocalizationPersistenceWriter = localizationPersistenceWriter; |
|||
LocalizationOptions = localizationOptions.Value; |
|||
LocalizationPersistenceOptions = localizationPersistenceOptions.Value; |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
public async virtual Task SaveAsync() |
|||
{ |
|||
if (!LocalizationPersistenceOptions.SaveStaticLocalizationsToPersistence) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var canWriterTexts = new List<LocalizableStringText>(); |
|||
|
|||
foreach (var localizationResource in LocalizationOptions.Resources) |
|||
{ |
|||
if (ShouldSaveToPersistence(localizationResource.Value)) |
|||
{ |
|||
if (!await LocalizationPersistenceWriter.WriteResourceAsync(localizationResource.Value)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
foreach (var language in LocalizationOptions.Languages) |
|||
{ |
|||
if (!await LocalizationPersistenceWriter.WriteLanguageAsync(language)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
using (CultureHelper.Use(language.CultureName, language.UiCultureName)) |
|||
{ |
|||
await FillCanWriterTextxAsync(localizationResource.Value, language, canWriterTexts); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (canWriterTexts.Any()) |
|||
{ |
|||
await LocalizationPersistenceWriter.WriteTextsAsync(canWriterTexts); |
|||
} |
|||
} |
|||
|
|||
protected virtual bool ShouldSaveToPersistence(LocalizationResourceBase localizationResource) |
|||
{ |
|||
var saveResource = false; |
|||
if (localizationResource.Contributors.Exists(IsMatchSaveToPersistenceContributor)) |
|||
{ |
|||
saveResource = true; |
|||
} |
|||
if (!saveResource) |
|||
{ |
|||
saveResource = LocalizationPersistenceOptions |
|||
.SaveToPersistenceResources |
|||
.Contains(localizationResource.ResourceName); |
|||
} |
|||
|
|||
return saveResource; |
|||
} |
|||
|
|||
protected virtual bool IsMatchSaveToPersistenceContributor(ILocalizationResourceContributor contributor) |
|||
{ |
|||
return typeof(LocalizationSaveToPersistenceContributor).IsAssignableFrom(contributor.GetType()); |
|||
} |
|||
|
|||
protected async virtual Task FillCanWriterTextxAsync( |
|||
LocalizationResourceBase localizationResource, |
|||
LanguageInfo language, |
|||
List<LocalizableStringText> canWriterTexts) |
|||
{ |
|||
var fillTexts = new Dictionary<string, LocalizedString>(); |
|||
var context = new LocalizationResourceInitializationContext(localizationResource, ServiceProvider); |
|||
foreach (var contributor in localizationResource.Contributors) |
|||
{ |
|||
if (contributor.IsDynamic) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
contributor.Initialize(context); |
|||
|
|||
await contributor.FillAsync(language.CultureName, fillTexts); |
|||
} |
|||
|
|||
var existsKeys = await LocalizationPersistenceWriter.GetExistsTextsAsync( |
|||
localizationResource.ResourceName, |
|||
language.CultureName, |
|||
fillTexts.Values.Select(x => x.Name)); |
|||
|
|||
var notExistsKeys = fillTexts.Values.Where(x => !existsKeys.Contains(x.Name)); |
|||
|
|||
foreach (var notExistsKey in notExistsKeys) |
|||
{ |
|||
if (!canWriterTexts.Any(x => x.CultureName == language.CultureName && x.Name == notExistsKey.Name)) |
|||
{ |
|||
canWriterTexts.Add( |
|||
new LocalizableStringText( |
|||
localizationResource.ResourceName, |
|||
language.CultureName, |
|||
notExistsKey.Name, |
|||
notExistsKey.Value)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using Microsoft.Extensions.Localization; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Localization.Persistence; |
|||
|
|||
public interface ILocalizationPersistenceReader |
|||
{ |
|||
LocalizedString GetOrNull(string resourceName, string cultureName, string name); |
|||
|
|||
void Fill(string resourceName, string cultureName, Dictionary<string, LocalizedString> dictionary); |
|||
|
|||
Task FillAsync(string resourceName, string cultureName, Dictionary<string, LocalizedString> dictionary); |
|||
|
|||
Task<IEnumerable<string>> GetSupportedCulturesAsync(); |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.Localization.Persistence; |
|||
public interface ILocalizationPersistenceWriter |
|||
{ |
|||
Task<bool> WriteLanguageAsync( |
|||
LanguageInfo language, |
|||
CancellationToken cancellationToken = default); |
|||
|
|||
Task<bool> WriteResourceAsync( |
|||
LocalizationResourceBase resource, |
|||
CancellationToken cancellationToken = default); |
|||
|
|||
Task<IEnumerable<string>> GetExistsTextsAsync( |
|||
string resourceName, |
|||
string cultureName, |
|||
IEnumerable<string> keys, |
|||
CancellationToken cancellationToken = default); |
|||
|
|||
Task<bool> WriteTextsAsync( |
|||
IEnumerable<LocalizableStringText> texts, |
|||
CancellationToken cancellationToken = default); |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
namespace LINGYUN.Abp.Localization.Persistence; |
|||
public class LocalizableStringText |
|||
{ |
|||
public LocalizableStringText( |
|||
string resourceName, |
|||
string cultureName, |
|||
string name, |
|||
string value) |
|||
{ |
|||
ResourceName = resourceName; |
|||
CultureName = cultureName; |
|||
Name = name; |
|||
Value = value; |
|||
} |
|||
|
|||
public string ResourceName { get; set; } |
|||
public string CultureName { get; set; } |
|||
public string Name { get; set; } |
|||
public string Value { get; set; } |
|||
public override string ToString() |
|||
{ |
|||
return $"[R]:{ResourceName},[C]:{CultureName ?? ""},[N]:{Name},[V]:{Value ?? ""}"; |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Localization; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.Localization.Persistence; |
|||
|
|||
public class LocalizationPersistenceContributor : ILocalizationResourceContributor |
|||
{ |
|||
public bool IsDynamic => true; |
|||
|
|||
private LocalizationResourceBase _resource; |
|||
private ILocalizationPersistenceReader _persistenceSupport; |
|||
public void Initialize(LocalizationResourceInitializationContext context) |
|||
{ |
|||
_resource = context.Resource; |
|||
_persistenceSupport = context.ServiceProvider.GetRequiredService<ILocalizationPersistenceReader>(); |
|||
} |
|||
|
|||
public virtual void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
_persistenceSupport.Fill(_resource.ResourceName, cultureName, dictionary); |
|||
} |
|||
|
|||
public async virtual Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
await _persistenceSupport.FillAsync(_resource.ResourceName, cultureName, dictionary); |
|||
} |
|||
|
|||
public virtual LocalizedString GetOrNull(string cultureName, string name) |
|||
{ |
|||
return _persistenceSupport.GetOrNull(_resource.ResourceName, cultureName, name); |
|||
} |
|||
|
|||
public async virtual Task<IEnumerable<string>> GetSupportedCulturesAsync() |
|||
{ |
|||
return await _persistenceSupport.GetSupportedCulturesAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
using Microsoft.Extensions.Localization; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.Localization.Persistence; |
|||
|
|||
/// <summary>
|
|||
/// 空接口, 使用此提供者可持久化本地化资源到持久设施
|
|||
/// </summary>
|
|||
public class LocalizationSaveToPersistenceContributor : ILocalizationResourceContributor |
|||
{ |
|||
public bool IsDynamic => true; |
|||
|
|||
public void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
} |
|||
|
|||
public Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public LocalizedString GetOrNull(string cultureName, string name) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
public Task<IEnumerable<string>> GetSupportedCulturesAsync() |
|||
{ |
|||
IEnumerable<string> emptyCultures = new string[0]; |
|||
|
|||
return Task.FromResult(emptyCultures); |
|||
} |
|||
|
|||
public void Initialize(LocalizationResourceInitializationContext context) |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
using Microsoft.Extensions.Localization; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Localization.Persistence; |
|||
|
|||
[Dependency(TryRegister = true)] |
|||
public class NoneLocalizationPersistenceReader : ILocalizationPersistenceReader, ISingletonDependency |
|||
{ |
|||
public void Fill(string resourceName, string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public Task FillAsync(string resourceName, string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public LocalizedString GetOrNull(string resourceName, string cultureName, string name) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
public Task<IEnumerable<string>> GetSupportedCulturesAsync() |
|||
{ |
|||
IEnumerable<string> emptyCultures = new string[0]; |
|||
|
|||
return Task.FromResult(emptyCultures); |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.Localization.Persistence; |
|||
|
|||
[Dependency(TryRegister = true)] |
|||
public class NoneLocalizationPersistenceWriter : ILocalizationPersistenceWriter, ISingletonDependency |
|||
{ |
|||
public Task<IEnumerable<string>> GetExistsTextsAsync( |
|||
string resourceName, |
|||
string cultureName, |
|||
IEnumerable<string> keys, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
return Task.FromResult(keys); |
|||
} |
|||
|
|||
public Task<bool> WriteLanguageAsync(LanguageInfo language, CancellationToken cancellationToken = default) |
|||
{ |
|||
return Task.FromResult(false); |
|||
} |
|||
|
|||
public Task<bool> WriteResourceAsync(LocalizationResourceBase resource, CancellationToken cancellationToken = default) |
|||
{ |
|||
return Task.FromResult(false); |
|||
} |
|||
|
|||
public Task<bool> WriteTextsAsync(IEnumerable<LocalizableStringText> texts, CancellationToken cancellationToken = default) |
|||
{ |
|||
return Task.FromResult(false); |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
using LINGYUN.Abp.Localization.Persistence; |
|||
using System; |
|||
|
|||
namespace Volo.Abp.Localization; |
|||
public static class AbpLocalizationOptionsExtensions |
|||
{ |
|||
public static void UsePersistence<TResource>( |
|||
this AbpLocalizationOptions options) |
|||
{ |
|||
options.Resources |
|||
.Get<TResource>() |
|||
.Contributors |
|||
.Add(new LocalizationSaveToPersistenceContributor()); |
|||
} |
|||
|
|||
public static void UsePersistence( |
|||
this AbpLocalizationOptions options, |
|||
Type localizationResourceType) |
|||
{ |
|||
options.Resources |
|||
.Get(localizationResourceType) |
|||
.Contributors |
|||
.Add(new LocalizationSaveToPersistenceContributor()); |
|||
} |
|||
|
|||
public static void UsePersistences( |
|||
this AbpLocalizationOptions options, |
|||
params Type[] localizationResourceTypes) |
|||
{ |
|||
foreach (var localizationResourceType in localizationResourceTypes) |
|||
{ |
|||
options.UsePersistence(localizationResourceType); |
|||
} |
|||
} |
|||
|
|||
public static void UseAllPersistence( |
|||
this AbpLocalizationOptions options) |
|||
{ |
|||
foreach (var resource in options.Resources) |
|||
{ |
|||
resource.Value.Contributors.Add(new LocalizationSaveToPersistenceContributor()); |
|||
} |
|||
} |
|||
} |
|||
@ -1,65 +0,0 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Localization; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace LINGYUN.Abp.LocalizationManagement; |
|||
|
|||
public class LocalizationManagementExternalContributor : ILocalizationResourceContributor |
|||
{ |
|||
public bool IsDynamic => true; |
|||
|
|||
private LocalizationResourceBase _resource; |
|||
|
|||
private ILocalizationStoreCache _localizationStoreCache; |
|||
private LocalizationStoreCacheInitializeContext _cacheInitializeContext; |
|||
|
|||
public void Initialize(LocalizationResourceInitializationContext context) |
|||
{ |
|||
_resource = context.Resource; |
|||
|
|||
_cacheInitializeContext = new LocalizationStoreCacheInitializeContext(context.ServiceProvider); |
|||
_localizationStoreCache = context.ServiceProvider.GetRequiredService<ILocalizationStoreCache>(); |
|||
} |
|||
|
|||
public virtual void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
AsyncHelper.RunSync(async () => await FillAsync(cultureName, dictionary)); |
|||
} |
|||
|
|||
public async virtual Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
await _localizationStoreCache.InitializeAsync(_cacheInitializeContext); |
|||
|
|||
var localizedStrings = _localizationStoreCache.GetAllLocalizedStrings(cultureName); |
|||
|
|||
var localizedStringsInResource = localizedStrings.GetOrDefault(_resource.ResourceName); |
|||
if (localizedStringsInResource != null) |
|||
{ |
|||
foreach (var localizedString in localizedStringsInResource) |
|||
{ |
|||
dictionary[localizedString.Key] = localizedString.Value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public virtual LocalizedString GetOrNull(string cultureName, string name) |
|||
{ |
|||
return _localizationStoreCache |
|||
.GetLocalizedStringOrNull(_resource.ResourceName, cultureName, name); |
|||
} |
|||
|
|||
public virtual Task<IEnumerable<string>> GetSupportedCulturesAsync() |
|||
{ |
|||
var languageInfos = _localizationStoreCache.GetLanguages(); |
|||
|
|||
IEnumerable<string> languages = languageInfos |
|||
.Select(x => x.CultureName) |
|||
.ToList(); |
|||
|
|||
return Task.FromResult(languages); |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
using LINGYUN.Abp.Localization.Persistence; |
|||
using Microsoft.Extensions.Localization; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace LINGYUN.Abp.LocalizationManagement; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
[ExposeServices( |
|||
typeof(ILocalizationPersistenceReader), |
|||
typeof(LocalizationManagementPersistenceReader))] |
|||
public class LocalizationManagementPersistenceReader : ILocalizationPersistenceReader, ITransientDependency |
|||
{ |
|||
private readonly ILocalizationStoreCache _localizationStoreCache; |
|||
private readonly LocalizationStoreCacheInitializeContext _cacheInitializeContext; |
|||
|
|||
public LocalizationManagementPersistenceReader( |
|||
IServiceProvider serviceProvider, |
|||
ILocalizationStoreCache localizationStoreCache) |
|||
{ |
|||
_localizationStoreCache = localizationStoreCache; |
|||
_cacheInitializeContext = new LocalizationStoreCacheInitializeContext(serviceProvider); |
|||
} |
|||
|
|||
public virtual void Fill(string resourceName, string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
AsyncHelper.RunSync(async () => await FillAsync(resourceName, cultureName, dictionary)); |
|||
} |
|||
|
|||
public async virtual Task FillAsync(string resourceName, string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
await _localizationStoreCache.InitializeAsync(_cacheInitializeContext); |
|||
|
|||
var localizedStrings = _localizationStoreCache.GetAllLocalizedStrings(cultureName); |
|||
|
|||
var localizedStringsInResource = localizedStrings.GetOrDefault(resourceName); |
|||
if (localizedStringsInResource != null) |
|||
{ |
|||
foreach (var localizedString in localizedStringsInResource) |
|||
{ |
|||
dictionary[localizedString.Key] = localizedString.Value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public virtual LocalizedString GetOrNull(string resourceName, string cultureName, string name) |
|||
{ |
|||
return _localizationStoreCache.GetLocalizedStringOrNull(resourceName, cultureName, name); |
|||
} |
|||
|
|||
public virtual Task<IEnumerable<string>> GetSupportedCulturesAsync() |
|||
{ |
|||
var languageInfos = _localizationStoreCache.GetLanguages(); |
|||
|
|||
IEnumerable<string> languages = languageInfos |
|||
.Select(x => x.CultureName) |
|||
.ToList(); |
|||
|
|||
return Task.FromResult(languages); |
|||
} |
|||
} |
|||
@ -0,0 +1,203 @@ |
|||
using LINGYUN.Abp.Localization.Persistence; |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.DistributedLocking; |
|||
using Volo.Abp.Guids; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.LocalizationManagement; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
[ExposeServices( |
|||
typeof(ILocalizationPersistenceWriter), |
|||
typeof(LocalizationManagementPersistenceWriter))] |
|||
public class LocalizationManagementPersistenceWriter : ILocalizationPersistenceWriter, ITransientDependency |
|||
{ |
|||
protected IDistributedCache Cache { get; } |
|||
protected IAbpDistributedLock DistributedLock { get; } |
|||
protected AbpDistributedCacheOptions CacheOptions { get; } |
|||
protected IApplicationInfoAccessor ApplicationInfoAccessor { get; } |
|||
|
|||
protected IGuidGenerator GuidGenerator { get; } |
|||
protected ILanguageRepository LanguageRepository { get; } |
|||
protected ITextRepository TextRepository { get; } |
|||
protected IResourceRepository ResourceRepository { get; } |
|||
|
|||
public LocalizationManagementPersistenceWriter( |
|||
IDistributedCache cache, |
|||
IGuidGenerator guidGenerator, |
|||
IAbpDistributedLock distributedLock, |
|||
ITextRepository textRepository, |
|||
ILanguageRepository languageRepository, |
|||
IResourceRepository resourceRepository, |
|||
IApplicationInfoAccessor applicationInfoAccessor, |
|||
IOptions<AbpDistributedCacheOptions> cacheOptions) |
|||
{ |
|||
Cache = cache; |
|||
GuidGenerator = guidGenerator; |
|||
DistributedLock = distributedLock; |
|||
LanguageRepository = languageRepository; |
|||
TextRepository = textRepository; |
|||
ResourceRepository = resourceRepository; |
|||
ApplicationInfoAccessor = applicationInfoAccessor; |
|||
CacheOptions = cacheOptions.Value; |
|||
} |
|||
|
|||
public async virtual Task<IEnumerable<string>> GetExistsTextsAsync( |
|||
string resourceName, |
|||
string cultureName, |
|||
IEnumerable<string> keys, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
if (!await ShouldCalculateTextsHash(keys, cancellationToken)) |
|||
{ |
|||
return keys; |
|||
} |
|||
|
|||
return await TextRepository.GetExistsKeysAsync( |
|||
resourceName, |
|||
cultureName, |
|||
keys, |
|||
cancellationToken); |
|||
} |
|||
|
|||
|
|||
|
|||
public async virtual Task<bool> WriteLanguageAsync( |
|||
LanguageInfo language, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
var commonDistributedLockKey = GetCommonDistributedLockKey("Language", language.CultureName); |
|||
await using var lockHandle = await DistributedLock.TryAcquireAsync(commonDistributedLockKey); |
|||
if (lockHandle == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (await LanguageRepository.FindByCultureNameAsync(language.CultureName, cancellationToken) == null) |
|||
{ |
|||
await LanguageRepository.InsertAsync( |
|||
new Language( |
|||
GuidGenerator.Create(), |
|||
language.CultureName, |
|||
language.UiCultureName, |
|||
language.DisplayName, |
|||
language.FlagIcon), |
|||
autoSave: true, |
|||
cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public async virtual Task<bool> WriteResourceAsync( |
|||
LocalizationResourceBase resource, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
var commonDistributedLockKey = GetCommonDistributedLockKey("Resource", resource.ResourceName); |
|||
await using var lockHandle = await DistributedLock.TryAcquireAsync(commonDistributedLockKey); |
|||
if (lockHandle == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (await ResourceRepository.FindByNameAsync(resource.ResourceName, cancellationToken) == null) |
|||
{ |
|||
await ResourceRepository.InsertAsync( |
|||
new Resource( |
|||
GuidGenerator.Create(), |
|||
resource.ResourceName, |
|||
resource.ResourceName, |
|||
resource.ResourceName, |
|||
resource.DefaultCultureName), |
|||
autoSave: true, |
|||
cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public async virtual Task<bool> WriteTextsAsync( |
|||
IEnumerable<LocalizableStringText> texts, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
if (!await ShouldCalculateTextsHash(texts.Select(x => x.Name), cancellationToken)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var cacheKey = GetApplicationHashCacheKey(); |
|||
var currentHash = CalculateTextsHash(texts.Select(x => x.Name)); |
|||
|
|||
var savedTexts = texts.Select(text => |
|||
new Text( |
|||
text.ResourceName, |
|||
text.CultureName, |
|||
text.Name, |
|||
text.Value)); |
|||
|
|||
await TextRepository.InsertManyAsync( |
|||
savedTexts, |
|||
autoSave: true, |
|||
cancellationToken: cancellationToken); |
|||
|
|||
await Cache.SetStringAsync( |
|||
cacheKey, |
|||
currentHash, |
|||
new DistributedCacheEntryOptions |
|||
{ |
|||
SlidingExpiration = TimeSpan.FromDays(30) |
|||
}, |
|||
cancellationToken); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private async Task<bool> ShouldCalculateTextsHash(IEnumerable<string> texts, CancellationToken cancellationToken = default) |
|||
{ |
|||
var cacheKey = GetApplicationHashCacheKey(); |
|||
var cachedHash = await Cache.GetStringAsync(cacheKey, cancellationToken); |
|||
|
|||
var currentHash = CalculateTextsHash(texts); |
|||
|
|||
if (cachedHash == currentHash) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return cachedHash != currentHash; |
|||
} |
|||
|
|||
private static string CalculateTextsHash(IEnumerable<string> texts) |
|||
{ |
|||
var stringBuilder = new StringBuilder(); |
|||
|
|||
stringBuilder.Append("LocalizableStrings:"); |
|||
stringBuilder.Append(texts.JoinAsString(",")); |
|||
|
|||
return stringBuilder |
|||
.ToString() |
|||
.ToMd5(); |
|||
} |
|||
|
|||
private string GetCommonDistributedLockKey( |
|||
string lockResourceName, |
|||
string lockResourceKey) |
|||
{ |
|||
return $"{CacheOptions.KeyPrefix}_Common_AbpLocalizationWriter_{lockResourceName}_{lockResourceKey}_Lock"; |
|||
} |
|||
|
|||
private string GetApplicationHashCacheKey() |
|||
{ |
|||
return $"{CacheOptions.KeyPrefix}_{ApplicationInfoAccessor.ApplicationName}_AbpLocalizationHash"; |
|||
} |
|||
} |
|||
@ -1,128 +0,0 @@ |
|||
using LINGYUN.Abp.Localization.Persistence; |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Guids; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace LINGYUN.Abp.LocalizationManagement; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
public class StaticLocalizationSaver : IStaticLocalizationSaver, ITransientDependency |
|||
{ |
|||
protected IGuidGenerator GuidGenerator { get; } |
|||
protected ILanguageRepository LanguageRepository { get; } |
|||
protected ITextRepository TextRepository { get; } |
|||
protected IResourceRepository ResourceRepository { get; } |
|||
protected IStringLocalizerFactory StringLocalizerFactory { get; } |
|||
protected AbpLocalizationOptions LocalizationOptions { get; } |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
protected AbpLocalizationPersistenceOptions LocalizationPersistenceOptions { get; } |
|||
|
|||
public StaticLocalizationSaver( |
|||
IGuidGenerator guidGenerator, |
|||
IServiceProvider serviceProvider, |
|||
ILanguageRepository languageRepository, |
|||
ITextRepository textRepository, |
|||
IResourceRepository resourceRepository, |
|||
IStringLocalizerFactory stringLocalizerFactory, |
|||
IOptions<AbpLocalizationOptions> localizationOptions, |
|||
IOptions<AbpLocalizationPersistenceOptions> localizationPersistenceOptions) |
|||
{ |
|||
GuidGenerator = guidGenerator; |
|||
ServiceProvider = serviceProvider; |
|||
LanguageRepository = languageRepository; |
|||
TextRepository = textRepository; |
|||
ResourceRepository = resourceRepository; |
|||
StringLocalizerFactory = stringLocalizerFactory; |
|||
LocalizationOptions = localizationOptions.Value; |
|||
LocalizationPersistenceOptions = localizationPersistenceOptions.Value; |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
public async virtual Task SaveAsync() |
|||
{ |
|||
var insertNewTexts = new List<Text>(); |
|||
|
|||
foreach (var language in LocalizationOptions.Languages) |
|||
{ |
|||
if (await LanguageRepository.FindByCultureNameAsync(language.CultureName) == null) |
|||
{ |
|||
await LanguageRepository.InsertAsync( |
|||
new Language( |
|||
GuidGenerator.Create(), |
|||
language.CultureName, |
|||
language.UiCultureName, |
|||
language.DisplayName, |
|||
language.FlagIcon)); |
|||
} |
|||
|
|||
foreach (var resource in LocalizationPersistenceOptions.SaveToPersistenceResources) |
|||
{ |
|||
using (CultureHelper.Use(language.CultureName, language.UiCultureName)) |
|||
{ |
|||
var localizationResource = LocalizationOptions.Resources.GetOrDefault(resource); |
|||
if (localizationResource == null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (await ResourceRepository.FindByNameAsync(localizationResource.ResourceName) == null) |
|||
{ |
|||
await ResourceRepository.InsertAsync( |
|||
new Resource( |
|||
GuidGenerator.Create(), |
|||
localizationResource.ResourceName, |
|||
localizationResource.ResourceName, |
|||
localizationResource.ResourceName, |
|||
localizationResource.DefaultCultureName)); |
|||
} |
|||
|
|||
var context = new LocalizationResourceInitializationContext(localizationResource, ServiceProvider); |
|||
foreach (var contributor in localizationResource.Contributors) |
|||
{ |
|||
if (contributor.IsDynamic) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
contributor.Initialize(context); |
|||
var fillTexts = new Dictionary<string, LocalizedString>(); |
|||
|
|||
await contributor.FillAsync(language.CultureName, fillTexts); |
|||
|
|||
var existsKeys = await TextRepository.GetExistsKeysAsync( |
|||
localizationResource.ResourceName, |
|||
language.CultureName, |
|||
fillTexts.Values.Select(x => x.Name)); |
|||
|
|||
var notExistsKeys = fillTexts.Values.Where(x => !existsKeys.Contains(x.Name)); |
|||
|
|||
foreach (var notExistsKey in notExistsKeys) |
|||
{ |
|||
if (!insertNewTexts.Any(x => x.CultureName == language.CultureName && x.Key == notExistsKey.Name)) |
|||
{ |
|||
insertNewTexts.Add( |
|||
new Text( |
|||
localizationResource.ResourceName, |
|||
language.CultureName, |
|||
notExistsKey.Name, |
|||
notExistsKey.Value)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (insertNewTexts.Any()) |
|||
{ |
|||
await TextRepository.InsertManyAsync(insertNewTexts); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,20 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<None Remove="LINGYUN\Abp\PermissionManagement\Localization\Application\Contracts\*.json" /> |
|||
<EmbeddedResource Include="LINGYUN\Abp\PermissionManagement\Localization\Application\Contracts\*.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.PermissionManagement.Application.Contracts" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,33 @@ |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Localization.ExceptionHandling; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.PermissionManagement.Localization; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
using VoloAbpPermissionManagementApplicationContractsModule = Volo.Abp.PermissionManagement.AbpPermissionManagementApplicationContractsModule; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement; |
|||
|
|||
[DependsOn( |
|||
typeof(VoloAbpPermissionManagementApplicationContractsModule))] |
|||
public class AbpPermissionManagementApplicationContractsModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpPermissionManagementApplicationContractsModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Get<AbpPermissionManagementResource>() |
|||
.AddVirtualJson("/LINGYUN/Abp/PermissionManagement/Localization/Application/Contracts"); |
|||
}); |
|||
|
|||
Configure<AbpExceptionLocalizationOptions>(options => |
|||
{ |
|||
options.MapCodeNamespace(PermissionManagementErrorCodes.Namespace, typeof(AbpPermissionManagementResource)); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
public class PermissionDefinitionCreateDto : PermissionDefinitionCreateOrUpdateDto |
|||
{ |
|||
[Required] |
|||
[DynamicStringLength(typeof(PermissionDefinitionRecordConsts), nameof(PermissionDefinitionRecordConsts.MaxNameLength))] |
|||
public string Name { get; set; } |
|||
|
|||
[Required] |
|||
[DynamicStringLength(typeof(PermissionGroupDefinitionRecordConsts), nameof(PermissionGroupDefinitionRecordConsts.MaxNameLength))] |
|||
public string GroupName { get; set; } |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
public abstract class PermissionDefinitionCreateOrUpdateDto : IHasExtraProperties |
|||
{ |
|||
[Required] |
|||
[DynamicStringLength(typeof(PermissionDefinitionRecordConsts), nameof(PermissionDefinitionRecordConsts.MaxDisplayNameLength))] |
|||
public string DisplayName { get; set; } |
|||
|
|||
[DynamicStringLength(typeof(PermissionDefinitionRecordConsts), nameof(PermissionDefinitionRecordConsts.MaxNameLength))] |
|||
public string ParentName { get; set; } |
|||
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
public MultiTenancySides? MultiTenancySide { get; set; } |
|||
|
|||
public List<string> Providers { get; set; } = new List<string>(); |
|||
|
|||
public List<string> StateCheckers { get; set; } = new List<string>(); |
|||
|
|||
public ExtraPropertyDictionary ExtraProperties { get; set; } = new ExtraPropertyDictionary(); |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
public class PermissionDefinitionDto : IHasExtraProperties |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string ParentName { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
|
|||
public string FormatedDisplayName { get; set; } |
|||
|
|||
public string GroupName { get; set; } |
|||
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
public MultiTenancySides? MultiTenancySide { get; set; } |
|||
|
|||
public List<string> Providers { get; set; } = new List<string>(); |
|||
|
|||
public List<string> StateCheckers { get; set; } = new List<string>(); |
|||
|
|||
public ExtraPropertyDictionary ExtraProperties { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
public class PermissionDefinitionGetListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public string Filter { get; set; } |
|||
|
|||
public string GroupName { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Domain.Entities; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
public class PermissionDefinitionUpdateDto : PermissionDefinitionCreateOrUpdateDto, IHasConcurrencyStamp |
|||
{ |
|||
[StringLength(40)] |
|||
public string ConcurrencyStamp { get; set; } |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
public class PermissionGroupDefinitionCreateDto : PermissionGroupDefinitionCreateOrUpdateDto |
|||
{ |
|||
[Required] |
|||
[DynamicStringLength(typeof(PermissionGroupDefinitionRecordConsts), nameof(PermissionGroupDefinitionRecordConsts.MaxNameLength))] |
|||
public string Name { get; set; } |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
public abstract class PermissionGroupDefinitionCreateOrUpdateDto : IHasExtraProperties |
|||
{ |
|||
[Required] |
|||
[DynamicStringLength(typeof(PermissionGroupDefinitionRecordConsts), nameof(PermissionGroupDefinitionRecordConsts.MaxDisplayNameLength))] |
|||
public string DisplayName { get; set; } |
|||
|
|||
public ExtraPropertyDictionary ExtraProperties { get; set; } = new ExtraPropertyDictionary(); |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
public class PermissionGroupDefinitionDto : IHasExtraProperties |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
|
|||
public string FormatedDisplayName { get; set; } |
|||
|
|||
public ExtraPropertyDictionary ExtraProperties { get; set; } |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
public class PermissionGroupDefinitionGetListInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
public string Filter { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Domain.Entities; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
public class PermissionGroupDefinitionUpdateDto : PermissionGroupDefinitionCreateOrUpdateDto, IHasConcurrencyStamp |
|||
{ |
|||
[StringLength(40)] |
|||
public string ConcurrencyStamp { get; set; } |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
public interface IPermissionDefinitionAppService : IApplicationService |
|||
{ |
|||
Task<PermissionDefinitionDto> GetAsync(string name); |
|||
|
|||
Task DeleteAsync(string name); |
|||
|
|||
Task<PermissionDefinitionDto> CreateAsync(PermissionDefinitionCreateDto input); |
|||
|
|||
Task<PermissionDefinitionDto> UpdateAsync(string name, PermissionDefinitionUpdateDto input); |
|||
|
|||
Task<PagedResultDto<PermissionDefinitionDto>> GetListAsync(PermissionDefinitionGetListInput input); |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
public interface IPermissionGroupDefinitionAppService : IApplicationService |
|||
{ |
|||
Task<PermissionGroupDefinitionDto> GetAsync(string name); |
|||
|
|||
Task DeleteAsync(string name); |
|||
|
|||
Task<PermissionGroupDefinitionDto> CreateAsync(PermissionGroupDefinitionCreateDto input); |
|||
|
|||
Task<PermissionGroupDefinitionDto> UpdateAsync(string name, PermissionGroupDefinitionUpdateDto input); |
|||
|
|||
Task<PagedResultDto<PermissionGroupDefinitionDto>> GetListAsync(PermissionGroupDefinitionGetListInput input); |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
{ |
|||
"culture": "en", |
|||
"texts": { |
|||
"Permission:PermissionManagement": "Permission Management", |
|||
"Permission:GroupDefinitions": "Group Definitions", |
|||
"Permission:PermissionDefinitions": "Permission Definitions", |
|||
"Permission:Create": "Create", |
|||
"Permission:Edit": "Edit", |
|||
"Permission:Delete": "Delete", |
|||
"PermissionManagement:001100": "Permission group {Name} already exists!", |
|||
"PermissionManagement:001404": "Permission group named {Name} not found!", |
|||
"PermissionManagement:002100": "Permission {Name} already exists!", |
|||
"PermissionManagement:002101": "The group definition of permission {Name} could not be retrieved!", |
|||
"PermissionManagement:0021404": "Permission named {Name} not found!" |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
{ |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"Permission:PermissionManagement": "权限管理", |
|||
"Permission:GroupDefinitions": "分组定义", |
|||
"Permission:PermissionDefinitions": "权限定义", |
|||
"Permission:Create": "新增", |
|||
"Permission:Edit": "修改", |
|||
"Permission:Delete": "删除", |
|||
"PermissionManagement:001100": "权限分组 {Name} 已经存在!", |
|||
"PermissionManagement:001404": "没有找到名为 {Name} 的权限分组!", |
|||
"PermissionManagement:002100": "权限 {Name} 已经存在!", |
|||
"PermissionManagement:002101": "未能检索到权限 {Name} 所在分组定义!", |
|||
"PermissionManagement:0021404": "没有找到名为 {Name} 的权限定义!" |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
namespace LINGYUN.Abp.PermissionManagement; |
|||
public static class PermissionManagementErrorCodes |
|||
{ |
|||
public const string Namespace = "PermissionManagement"; |
|||
|
|||
public static class GroupDefinition |
|||
{ |
|||
private const string Prefix = Namespace + ":001"; |
|||
|
|||
public const string AlreayNameExists = Prefix + "100"; |
|||
|
|||
public const string NameNotFount = Prefix + "404"; |
|||
} |
|||
|
|||
public static class Definition |
|||
{ |
|||
private const string Prefix = Namespace + ":002"; |
|||
|
|||
public const string AlreayNameExists = Prefix + "100"; |
|||
|
|||
public const string FailedGetGroup = Prefix + "101"; |
|||
|
|||
public const string NameNotFount = Prefix + "404"; |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.PermissionManagement.Localization; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Permissions; |
|||
|
|||
public class PermissionManagementPermissionDefinitionProvider : PermissionDefinitionProvider |
|||
{ |
|||
public override void Define(IPermissionDefinitionContext context) |
|||
{ |
|||
var permissionGroup = context.AddGroup( |
|||
PermissionManagementPermissionNames.GroupName, |
|||
L("Permission:PermissionManagement")); |
|||
|
|||
var groupDefinition = permissionGroup.AddPermission( |
|||
PermissionManagementPermissionNames.GroupDefinition.Default, |
|||
L("Permission:GroupDefinitions"), |
|||
MultiTenancySides.Host); |
|||
groupDefinition.AddChild( |
|||
PermissionManagementPermissionNames.GroupDefinition.Create, |
|||
L("Permission:Create"), |
|||
MultiTenancySides.Host); |
|||
groupDefinition.AddChild( |
|||
PermissionManagementPermissionNames.GroupDefinition.Update, |
|||
L("Permission:Edit"), |
|||
MultiTenancySides.Host); |
|||
groupDefinition.AddChild( |
|||
PermissionManagementPermissionNames.GroupDefinition.Delete, |
|||
L("Permission:Delete"), |
|||
MultiTenancySides.Host); |
|||
|
|||
var permissionDefinition = permissionGroup.AddPermission( |
|||
PermissionManagementPermissionNames.Definition.Default, |
|||
L("Permission:PermissionDefinitions"), |
|||
MultiTenancySides.Host); |
|||
permissionDefinition.AddChild( |
|||
PermissionManagementPermissionNames.Definition.Create, |
|||
L("Permission:Create"), |
|||
MultiTenancySides.Host); |
|||
permissionDefinition.AddChild( |
|||
PermissionManagementPermissionNames.Definition.Update, |
|||
L("Permission:Edit"), |
|||
MultiTenancySides.Host); |
|||
permissionDefinition.AddChild( |
|||
PermissionManagementPermissionNames.Definition.Delete, |
|||
L("Permission:Delete"), |
|||
MultiTenancySides.Host); |
|||
} |
|||
|
|||
private static LocalizableString L(string name) |
|||
{ |
|||
return LocalizableString.Create<AbpPermissionManagementResource>(name); |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
namespace LINGYUN.Abp.PermissionManagement.Permissions; |
|||
public static class PermissionManagementPermissionNames |
|||
{ |
|||
public const string GroupName = "PermissionManagement"; |
|||
|
|||
public static class GroupDefinition |
|||
{ |
|||
public const string Default = GroupName + ".GroupDefinitions"; |
|||
|
|||
public const string Create = Default + ".Create"; |
|||
public const string Update = Default + ".Update"; |
|||
public const string Delete = Default + ".Delete"; |
|||
} |
|||
|
|||
public static class Definition |
|||
{ |
|||
public const string Default = GroupName + ".Definitions"; |
|||
|
|||
public const string Create = Default + ".Create"; |
|||
public const string Update = Default + ".Update"; |
|||
public const string Delete = Default + ".Delete"; |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.PermissionManagement.Application" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.PermissionManagement.Application.Contracts\LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,12 @@ |
|||
using Volo.Abp.Modularity; |
|||
using VoloAbpPermissionManagementApplicationModule = Volo.Abp.PermissionManagement.AbpPermissionManagementApplicationModule; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpPermissionManagementApplicationContractsModule), |
|||
typeof(VoloAbpPermissionManagementApplicationModule))] |
|||
public class AbpPermissionManagementApplicationModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Entities.Events; |
|||
using Volo.Abp.EventBus; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.Threading; |
|||
using Volo.Abp.Timing; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
public class DynamicPermissionDefinitionStoreCacheInvalidator : |
|||
ILocalEventHandler<EntityChangedEventData<PermissionGroupDefinitionRecord>>, |
|||
ILocalEventHandler<EntityChangedEventData<PermissionDefinitionRecord>>, |
|||
ITransientDependency |
|||
{ |
|||
private readonly IDynamicPermissionDefinitionStoreInMemoryCache _storeCache; |
|||
|
|||
private readonly IClock _clock; |
|||
private readonly IDistributedCache _distributedCache; |
|||
private readonly AbpDistributedCacheOptions _cacheOptions; |
|||
|
|||
public DynamicPermissionDefinitionStoreCacheInvalidator( |
|||
IClock clock, |
|||
IDistributedCache distributedCache, |
|||
IDynamicPermissionDefinitionStoreInMemoryCache storeCache, |
|||
IOptions<AbpDistributedCacheOptions> cacheOptions) |
|||
{ |
|||
_storeCache = storeCache; |
|||
_clock = clock; |
|||
_distributedCache = distributedCache; |
|||
_cacheOptions = cacheOptions.Value; |
|||
} |
|||
|
|||
public async virtual Task HandleEventAsync(EntityChangedEventData<PermissionGroupDefinitionRecord> eventData) |
|||
{ |
|||
await RemoveStampInDistributedCacheAsync(); |
|||
} |
|||
|
|||
public async virtual Task HandleEventAsync(EntityChangedEventData<PermissionDefinitionRecord> eventData) |
|||
{ |
|||
await RemoveStampInDistributedCacheAsync(); |
|||
} |
|||
|
|||
protected async virtual Task RemoveStampInDistributedCacheAsync() |
|||
{ |
|||
using (await _storeCache.SyncSemaphore.LockAsync()) |
|||
{ |
|||
var cacheKey = GetCommonStampCacheKey(); |
|||
|
|||
await _distributedCache.RemoveAsync(cacheKey); |
|||
|
|||
_storeCache.CacheStamp = Guid.NewGuid().ToString(); |
|||
_storeCache.LastCheckTime = _clock.Now.AddMinutes(-5); |
|||
} |
|||
} |
|||
|
|||
protected virtual string GetCommonStampCacheKey() |
|||
{ |
|||
return $"{_cacheOptions.KeyPrefix}_AbpInMemoryPermissionCacheStamp"; |
|||
} |
|||
} |
|||
@ -0,0 +1,331 @@ |
|||
using LINGYUN.Abp.PermissionManagement.Permissions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.PermissionManagement; |
|||
using Volo.Abp.SimpleStateChecking; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
[Authorize(PermissionManagementPermissionNames.Definition.Default)] |
|||
public class PermissionDefinitionAppService : PermissionManagementAppServiceBase, IPermissionDefinitionAppService |
|||
{ |
|||
private readonly ISimpleStateCheckerSerializer _simpleStateCheckerSerializer; |
|||
private readonly ILocalizableStringSerializer _localizableStringSerializer; |
|||
private readonly IPermissionDefinitionManager _permissionDefinitionManager; |
|||
|
|||
private readonly IPermissionDefinitionRecordRepository _definitionRepository; |
|||
private readonly IRepository<PermissionDefinitionRecord, Guid> _definitionBasicRepository; |
|||
|
|||
public PermissionDefinitionAppService( |
|||
ILocalizableStringSerializer localizableStringSerializer, |
|||
IPermissionDefinitionManager permissionDefinitionManager, |
|||
ISimpleStateCheckerSerializer simpleStateCheckerSerializer, |
|||
IPermissionDefinitionRecordRepository definitionRepository, |
|||
IRepository<PermissionDefinitionRecord, Guid> definitionBasicRepository) |
|||
{ |
|||
_localizableStringSerializer = localizableStringSerializer; |
|||
_permissionDefinitionManager = permissionDefinitionManager; |
|||
_simpleStateCheckerSerializer = simpleStateCheckerSerializer; |
|||
_definitionRepository = definitionRepository; |
|||
_definitionBasicRepository = definitionBasicRepository; |
|||
} |
|||
|
|||
[Authorize(PermissionManagementPermissionNames.Definition.Create)] |
|||
public async virtual Task<PermissionDefinitionDto> CreateAsync(PermissionDefinitionCreateDto input) |
|||
{ |
|||
if (await _permissionDefinitionManager.GetOrNullAsync(input.Name) != null) |
|||
{ |
|||
throw new BusinessException(PermissionManagementErrorCodes.Definition.AlreayNameExists) |
|||
.WithData(nameof(PermissionDefinitionRecord.Name), input.Name); |
|||
} |
|||
|
|||
var groupDefinition = await _permissionDefinitionManager.GetGroupOrNullAsync(input.GroupName); |
|||
if (groupDefinition == null) |
|||
{ |
|||
throw new BusinessException(PermissionManagementErrorCodes.GroupDefinition.NameNotFount) |
|||
.WithData(nameof(PermissionGroupDefinitionRecord.Name), input.GroupName); |
|||
} |
|||
|
|||
var definitionRecord = new PermissionDefinitionRecord( |
|||
GuidGenerator.Create(), |
|||
groupDefinition.Name, |
|||
input.Name, |
|||
input.ParentName, |
|||
input.DisplayName, |
|||
input.IsEnabled); |
|||
|
|||
if (input.MultiTenancySide.HasValue) |
|||
{ |
|||
definitionRecord.MultiTenancySide = input.MultiTenancySide.Value; |
|||
} |
|||
|
|||
if (input.Providers.Any()) |
|||
{ |
|||
definitionRecord.Providers = input.Providers.JoinAsString(","); |
|||
} |
|||
|
|||
if (input.StateCheckers.Any()) |
|||
{ |
|||
definitionRecord.StateCheckers = input.StateCheckers.JoinAsString(","); |
|||
} |
|||
|
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
definitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
await _definitionRepository.InsertAsync(definitionRecord); |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
|
|||
var dto = await DefinitionRecordToDto(definitionRecord); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
[Authorize(PermissionManagementPermissionNames.Definition.Delete)] |
|||
public async virtual Task DeleteAsync(string name) |
|||
{ |
|||
var definitionRecord = await FindByNameAsync(name); |
|||
|
|||
if (definitionRecord == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await _definitionRepository.DeleteAsync(definitionRecord); |
|||
} |
|||
|
|||
public async virtual Task<PermissionDefinitionDto> GetAsync(string name) |
|||
{ |
|||
var definition = await _permissionDefinitionManager.GetOrNullAsync(name); |
|||
if (definition == null) |
|||
{ |
|||
throw new BusinessException(PermissionManagementErrorCodes.Definition.NameNotFount) |
|||
.WithData(nameof(PermissionDefinitionRecord.Name), name); |
|||
} |
|||
|
|||
var groupDefinition = await GetGroupDefinition(definition); |
|||
|
|||
var dto = await DefinitionToDto(groupDefinition, definition); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
public async virtual Task<PagedResultDto<PermissionDefinitionDto>> GetListAsync(PermissionDefinitionGetListInput input) |
|||
{ |
|||
var permissions = new List<PermissionDefinitionDto>(); |
|||
|
|||
IReadOnlyList<PermissionDefinition> definitionPermissions; |
|||
|
|||
if (!input.GroupName.IsNullOrWhiteSpace()) |
|||
{ |
|||
var group = await _permissionDefinitionManager.GetGroupOrNullAsync(input.GroupName); |
|||
if (group == null) |
|||
{ |
|||
return new PagedResultDto<PermissionDefinitionDto>(0, permissions); |
|||
} |
|||
|
|||
definitionPermissions = group.GetPermissionsWithChildren(); |
|||
} |
|||
else |
|||
{ |
|||
definitionPermissions = await _permissionDefinitionManager.GetPermissionsAsync(); |
|||
} |
|||
|
|||
var definitionFilter = definitionPermissions.AsQueryable() |
|||
.WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => x.Name.Contains(input.Filter) || |
|||
(x.Parent != null && x.Parent.Name.Contains(input.Filter))); |
|||
|
|||
var sorting = input.Sorting; |
|||
if (sorting.IsNullOrWhiteSpace()) |
|||
{ |
|||
sorting = nameof(PermissionDefinitionRecord.Name); |
|||
} |
|||
|
|||
var filterDefinitionCount = definitionFilter.Count(); |
|||
var filterDefinitions = definitionFilter |
|||
.OrderBy(sorting) |
|||
.PageBy(input.SkipCount, input.MaxResultCount); |
|||
|
|||
foreach (var definition in filterDefinitions) |
|||
{ |
|||
var groupDefinition = await GetGroupDefinition(definition); |
|||
var Dto = await DefinitionToDto(groupDefinition, definition); |
|||
|
|||
permissions.Add(Dto); |
|||
} |
|||
|
|||
return new PagedResultDto<PermissionDefinitionDto>(filterDefinitionCount, permissions); |
|||
} |
|||
|
|||
[Authorize(PermissionManagementPermissionNames.Definition.Update)] |
|||
public async virtual Task<PermissionDefinitionDto> UpdateAsync(string name, PermissionDefinitionUpdateDto input) |
|||
{ |
|||
var definition = await _permissionDefinitionManager.GetOrNullAsync(name); |
|||
var definitionRecord = await FindByNameAsync(name); |
|||
|
|||
if (definitionRecord == null) |
|||
{ |
|||
var groupDefinition = await GetGroupDefinition(definition); |
|||
definitionRecord = new PermissionDefinitionRecord( |
|||
GuidGenerator.Create(), |
|||
groupDefinition.Name, |
|||
name, |
|||
input.ParentName, |
|||
input.DisplayName, |
|||
input.IsEnabled); |
|||
|
|||
if (input.MultiTenancySide.HasValue) |
|||
{ |
|||
definitionRecord.MultiTenancySide = input.MultiTenancySide.Value; |
|||
} |
|||
|
|||
if (input.Providers.Any()) |
|||
{ |
|||
definitionRecord.Providers = input.Providers.JoinAsString(","); |
|||
} |
|||
|
|||
if (input.StateCheckers.Any()) |
|||
{ |
|||
definitionRecord.StateCheckers = input.StateCheckers.JoinAsString(","); |
|||
} |
|||
|
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
definitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
definitionRecord = await _definitionBasicRepository.InsertAsync(definitionRecord); |
|||
} |
|||
else |
|||
{ |
|||
definitionRecord.ExtraProperties.Clear(); |
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
definitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
if (input.MultiTenancySide.HasValue) |
|||
{ |
|||
definitionRecord.MultiTenancySide = input.MultiTenancySide.Value; |
|||
} |
|||
|
|||
if (input.Providers.Any()) |
|||
{ |
|||
definitionRecord.Providers = input.Providers.JoinAsString(","); |
|||
} |
|||
|
|||
if (input.StateCheckers.Any()) |
|||
{ |
|||
definitionRecord.StateCheckers = input.StateCheckers.JoinAsString(","); |
|||
} |
|||
|
|||
if (!string.Equals(definitionRecord.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase)) |
|||
{ |
|||
definitionRecord.DisplayName = input.DisplayName; |
|||
} |
|||
|
|||
definitionRecord = await _definitionBasicRepository.UpdateAsync(definitionRecord); |
|||
} |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
|
|||
var dto = await DefinitionRecordToDto(definitionRecord); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
protected async virtual Task<PermissionDefinitionRecord> FindByNameAsync(string name) |
|||
{ |
|||
var DefinitionFilter = await _definitionBasicRepository.GetQueryableAsync(); |
|||
|
|||
var definitionRecord = await AsyncExecuter.FirstOrDefaultAsync( |
|||
DefinitionFilter.Where(x => x.Name == name)); |
|||
|
|||
return definitionRecord; |
|||
} |
|||
|
|||
protected async virtual Task<PermissionGroupDefinition> GetGroupDefinition(PermissionDefinition definition) |
|||
{ |
|||
var groups = await _permissionDefinitionManager.GetGroupsAsync(); |
|||
|
|||
foreach (var group in groups) |
|||
{ |
|||
if (group.GetPermissionOrNull(definition.Name) != null) |
|||
{ |
|||
return group; |
|||
} |
|||
} |
|||
|
|||
throw new BusinessException(PermissionManagementErrorCodes.Definition.FailedGetGroup) |
|||
.WithData(nameof(PermissionDefinitionRecord.Name), definition.Name); |
|||
} |
|||
|
|||
protected async virtual Task<PermissionDefinitionDto> DefinitionRecordToDto(PermissionDefinitionRecord definitionRecord) |
|||
{ |
|||
var dto = new PermissionDefinitionDto |
|||
{ |
|||
Name = definitionRecord.Name, |
|||
GroupName = definitionRecord.GroupName, |
|||
ParentName = definitionRecord.ParentName, |
|||
IsEnabled = definitionRecord.IsEnabled, |
|||
FormatedDisplayName = definitionRecord.DisplayName, |
|||
Providers = definitionRecord.Providers.Split(',').ToList(), |
|||
StateCheckers = definitionRecord.StateCheckers.Split(',').ToList(), |
|||
MultiTenancySide = definitionRecord.MultiTenancySide, |
|||
}; |
|||
|
|||
var displayName = _localizableStringSerializer.Deserialize(definitionRecord.DisplayName); |
|||
dto.DisplayName = await displayName.LocalizeAsync(StringLocalizerFactory); |
|||
|
|||
foreach (var property in definitionRecord.ExtraProperties) |
|||
{ |
|||
dto.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
protected async virtual Task<PermissionDefinitionDto> DefinitionToDto(PermissionGroupDefinition groupDefinition, PermissionDefinition definition) |
|||
{ |
|||
var dto = new PermissionDefinitionDto |
|||
{ |
|||
Name = definition.Name, |
|||
GroupName = groupDefinition.Name, |
|||
ParentName = definition.Parent?.Name, |
|||
IsEnabled = definition.IsEnabled, |
|||
Providers = definition.Providers, |
|||
MultiTenancySide = definition.MultiTenancySide, |
|||
}; |
|||
|
|||
if (definition.StateCheckers.Any()) |
|||
{ |
|||
var stateCheckers = _simpleStateCheckerSerializer.Serialize(definition.StateCheckers); |
|||
dto.StateCheckers = stateCheckers.Split(',').ToList(); |
|||
} |
|||
|
|||
if (definition.DisplayName != null) |
|||
{ |
|||
dto.DisplayName = await definition.DisplayName.LocalizeAsync(StringLocalizerFactory); |
|||
dto.FormatedDisplayName = _localizableStringSerializer.Serialize(definition.DisplayName); |
|||
} |
|||
|
|||
foreach (var property in definition.Properties) |
|||
{ |
|||
dto.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
return dto; |
|||
} |
|||
} |
|||
@ -0,0 +1,216 @@ |
|||
using LINGYUN.Abp.PermissionManagement.Permissions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Dynamic.Core; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.PermissionManagement; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.Definitions; |
|||
|
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Default)] |
|||
public class PermissionGroupDefinitionAppService : PermissionManagementAppServiceBase, IPermissionGroupDefinitionAppService |
|||
{ |
|||
private readonly ILocalizableStringSerializer _localizableStringSerializer; |
|||
private readonly IPermissionDefinitionManager _permissionDefinitionManager; |
|||
|
|||
private readonly IPermissionGroupDefinitionRecordRepository _groupDefinitionRepository; |
|||
private readonly IRepository<PermissionGroupDefinitionRecord, Guid> _groupDefinitionBasicRepository; |
|||
|
|||
public PermissionGroupDefinitionAppService( |
|||
ILocalizableStringSerializer localizableStringSerializer, |
|||
IPermissionDefinitionManager permissionDefinitionManager, |
|||
IPermissionGroupDefinitionRecordRepository groupDefinitionRepository, |
|||
IRepository<PermissionGroupDefinitionRecord, Guid> groupDefinitionBasicRepository) |
|||
{ |
|||
_localizableStringSerializer = localizableStringSerializer; |
|||
_permissionDefinitionManager = permissionDefinitionManager; |
|||
_groupDefinitionRepository = groupDefinitionRepository; |
|||
_groupDefinitionBasicRepository = groupDefinitionBasicRepository; |
|||
} |
|||
|
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Create)] |
|||
public async virtual Task<PermissionGroupDefinitionDto> CreateAsync(PermissionGroupDefinitionCreateDto input) |
|||
{ |
|||
if (await _permissionDefinitionManager.GetGroupOrNullAsync(input.Name) != null) |
|||
{ |
|||
throw new BusinessException(PermissionManagementErrorCodes.GroupDefinition.AlreayNameExists) |
|||
.WithData(nameof(PermissionGroupDefinitionRecord.Name), input.Name); |
|||
} |
|||
|
|||
var groupDefinitionRecord = new PermissionGroupDefinitionRecord( |
|||
GuidGenerator.Create(), |
|||
input.Name, |
|||
input.DisplayName); |
|||
|
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
groupDefinitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
await _groupDefinitionRepository.InsertAsync(groupDefinitionRecord); |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
|
|||
var dto = await GroupDefinitionRecordToDto(groupDefinitionRecord); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Delete)] |
|||
public async virtual Task DeleteAsync(string name) |
|||
{ |
|||
var groupDefinitionRecord = await FindByNameAsync(name); |
|||
|
|||
if (groupDefinitionRecord == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await _groupDefinitionRepository.DeleteAsync(groupDefinitionRecord); |
|||
} |
|||
|
|||
public async virtual Task<PermissionGroupDefinitionDto> GetAsync(string name) |
|||
{ |
|||
var groupDefinition = await _permissionDefinitionManager.GetGroupOrNullAsync(name); |
|||
if (groupDefinition == null) |
|||
{ |
|||
throw new BusinessException(PermissionManagementErrorCodes.GroupDefinition.NameNotFount) |
|||
.WithData(nameof(PermissionGroupDefinitionRecord.Name), name); |
|||
} |
|||
|
|||
var dto = await GroupDefinitionToDto(groupDefinition); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
public async virtual Task<PagedResultDto<PermissionGroupDefinitionDto>> GetListAsync(PermissionGroupDefinitionGetListInput input) |
|||
{ |
|||
var groups = new List<PermissionGroupDefinitionDto>(); |
|||
|
|||
var groupDefinitions = await _permissionDefinitionManager.GetGroupsAsync(); |
|||
|
|||
var groupDefinitionFilter = groupDefinitions.AsQueryable() |
|||
.WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => x.Name.Contains(input.Filter)); |
|||
|
|||
var sorting = input.Sorting; |
|||
if (sorting.IsNullOrWhiteSpace()) |
|||
{ |
|||
sorting = nameof(PermissionDefinitionRecord.Name); |
|||
} |
|||
|
|||
var filterGroupDefinitionCount = groupDefinitionFilter.Count(); |
|||
var filterGroupDefinitions = groupDefinitionFilter |
|||
.OrderBy(sorting) |
|||
.PageBy(input.SkipCount, input.MaxResultCount); |
|||
|
|||
foreach (var groupDefinition in filterGroupDefinitions) |
|||
{ |
|||
var groupDto = await GroupDefinitionToDto(groupDefinition); |
|||
|
|||
groups.Add(groupDto); |
|||
} |
|||
|
|||
return new PagedResultDto<PermissionGroupDefinitionDto>(filterGroupDefinitionCount, groups); |
|||
} |
|||
|
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Update)] |
|||
public async virtual Task<PermissionGroupDefinitionDto> UpdateAsync(string name, PermissionGroupDefinitionUpdateDto input) |
|||
{ |
|||
var groupDefinition = await _permissionDefinitionManager.GetGroupOrNullAsync(name); |
|||
var groupDefinitionRecord = await FindByNameAsync(name); |
|||
|
|||
if (groupDefinitionRecord == null) |
|||
{ |
|||
groupDefinitionRecord = new PermissionGroupDefinitionRecord( |
|||
GuidGenerator.Create(), |
|||
name, |
|||
input.DisplayName); |
|||
|
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
groupDefinitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
groupDefinitionRecord = await _groupDefinitionBasicRepository.InsertAsync(groupDefinitionRecord); |
|||
} |
|||
else |
|||
{ |
|||
groupDefinitionRecord.ExtraProperties.Clear(); |
|||
foreach (var property in input.ExtraProperties) |
|||
{ |
|||
groupDefinitionRecord.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
if (!string.Equals(groupDefinitionRecord.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase)) |
|||
{ |
|||
groupDefinitionRecord.DisplayName = input.DisplayName; |
|||
} |
|||
|
|||
groupDefinitionRecord = await _groupDefinitionBasicRepository.UpdateAsync(groupDefinitionRecord); |
|||
} |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
|
|||
var dto = await GroupDefinitionRecordToDto(groupDefinitionRecord); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
protected async virtual Task<PermissionGroupDefinitionRecord> FindByNameAsync(string name) |
|||
{ |
|||
var groupDefinitionFilter = await _groupDefinitionBasicRepository.GetQueryableAsync(); |
|||
|
|||
var groupDefinitionRecord = await AsyncExecuter.FirstOrDefaultAsync( |
|||
groupDefinitionFilter.Where(x => x.Name == name)); |
|||
|
|||
return groupDefinitionRecord; |
|||
} |
|||
|
|||
protected async virtual Task<PermissionGroupDefinitionDto> GroupDefinitionRecordToDto(PermissionGroupDefinitionRecord groupDefinitionRecord) |
|||
{ |
|||
var groupDto = new PermissionGroupDefinitionDto |
|||
{ |
|||
Name = groupDefinitionRecord.Name, |
|||
FormatedDisplayName = groupDefinitionRecord.DisplayName, |
|||
}; |
|||
|
|||
var displayName = _localizableStringSerializer.Deserialize(groupDefinitionRecord.DisplayName); |
|||
groupDto.DisplayName = await displayName.LocalizeAsync(StringLocalizerFactory); |
|||
|
|||
foreach (var property in groupDefinitionRecord.ExtraProperties) |
|||
{ |
|||
groupDto.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
return groupDto; |
|||
} |
|||
|
|||
protected async virtual Task<PermissionGroupDefinitionDto> GroupDefinitionToDto(PermissionGroupDefinition groupDefinition) |
|||
{ |
|||
var groupDto = new PermissionGroupDefinitionDto |
|||
{ |
|||
Name = groupDefinition.Name |
|||
}; |
|||
|
|||
if (groupDefinition.DisplayName != null) |
|||
{ |
|||
groupDto.DisplayName = await groupDefinition.DisplayName.LocalizeAsync(StringLocalizerFactory); |
|||
groupDto.FormatedDisplayName = _localizableStringSerializer.Serialize(groupDefinition.DisplayName); |
|||
} |
|||
|
|||
foreach (var property in groupDefinition.Properties) |
|||
{ |
|||
groupDto.SetProperty(property.Key, property.Value); |
|||
} |
|||
|
|||
return groupDto; |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.PermissionManagement.Localization; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement; |
|||
public abstract class PermissionManagementAppServiceBase : ApplicationService |
|||
{ |
|||
protected PermissionManagementAppServiceBase() |
|||
{ |
|||
LocalizationResource = typeof(AbpPermissionManagementResource); |
|||
ObjectMapperContext = typeof(AbpPermissionManagementApplicationModule); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions; |
|||
public static class IPermissionDefinitionManagerExtensions |
|||
{ |
|||
public async static Task<PermissionGroupDefinition> GetGroupOrNullAsync( |
|||
this IPermissionDefinitionManager permissionDefinitionManager, |
|||
string name |
|||
) |
|||
{ |
|||
var groups = await permissionDefinitionManager.GetGroupsAsync(); |
|||
|
|||
return groups.FirstOrDefault(x => x.Name == name); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.PermissionManagement.Application.Contracts\LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,28 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Mvc.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.PermissionManagement.Localization; |
|||
using VoloAbpPermissionManagementHttpApiModule = Volo.Abp.PermissionManagement.HttpApi.AbpPermissionManagementHttpApiModule; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.HttpApi; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpPermissionManagementApplicationContractsModule), |
|||
typeof(VoloAbpPermissionManagementHttpApiModule))] |
|||
public class AbpPermissionManagementHttpApiModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
PreConfigure(delegate (IMvcBuilder mvcBuilder) |
|||
{ |
|||
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpPermissionManagementHttpApiModule)!.Assembly); |
|||
}); |
|||
|
|||
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
|||
{ |
|||
options.AddAssemblyResource( |
|||
typeof(AbpPermissionManagementResource), |
|||
typeof(AbpPermissionManagementApplicationContractsModule).Assembly); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using LINGYUN.Abp.PermissionManagement.Definitions; |
|||
using LINGYUN.Abp.PermissionManagement.Permissions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.PermissionManagement; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.HttpApi.Definitions; |
|||
|
|||
[Controller] |
|||
[Authorize(PermissionManagementPermissionNames.Definition.Default)] |
|||
[RemoteService(Name = PermissionManagementRemoteServiceConsts.RemoteServiceName)] |
|||
[Area(PermissionManagementRemoteServiceConsts.ModuleName)] |
|||
[Route("api/permission-management/definitions")] |
|||
public class PermissionDefinitionController : PermissionManagementControllerBase, IPermissionDefinitionAppService |
|||
{ |
|||
private readonly IPermissionDefinitionAppService _service; |
|||
|
|||
public PermissionDefinitionController(IPermissionDefinitionAppService service) |
|||
{ |
|||
_service = service; |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Authorize(PermissionManagementPermissionNames.Definition.Create)] |
|||
public virtual Task<PermissionDefinitionDto> CreateAsync(PermissionDefinitionCreateDto input) |
|||
{ |
|||
return _service.CreateAsync(input); |
|||
} |
|||
|
|||
[HttpDelete] |
|||
[Route("{name}")] |
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Delete)] |
|||
public virtual Task DeleteAsync(string name) |
|||
{ |
|||
return _service.DeleteAsync(name); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("{name}")] |
|||
[Authorize(PermissionManagementPermissionNames.Definition.Delete)] |
|||
public virtual Task<PermissionDefinitionDto> GetAsync(string name) |
|||
{ |
|||
return _service.GetAsync(name); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public virtual Task<PagedResultDto<PermissionDefinitionDto>> GetListAsync(PermissionDefinitionGetListInput input) |
|||
{ |
|||
return _service.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("{name}")] |
|||
[Authorize(PermissionManagementPermissionNames.Definition.Update)] |
|||
public virtual Task<PermissionDefinitionDto> UpdateAsync(string name, PermissionDefinitionUpdateDto input) |
|||
{ |
|||
return _service.UpdateAsync(name, input); |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using LINGYUN.Abp.PermissionManagement.Definitions; |
|||
using LINGYUN.Abp.PermissionManagement.Permissions; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.PermissionManagement; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.HttpApi.Definitions; |
|||
|
|||
[Controller] |
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Default)] |
|||
[RemoteService(Name = PermissionManagementRemoteServiceConsts.RemoteServiceName)] |
|||
[Area(PermissionManagementRemoteServiceConsts.ModuleName)] |
|||
[Route("api/permission-management/definitions/groups")] |
|||
public class PermissionGroupDefinitionController : PermissionManagementControllerBase, IPermissionGroupDefinitionAppService |
|||
{ |
|||
private readonly IPermissionGroupDefinitionAppService _service; |
|||
|
|||
public PermissionGroupDefinitionController(IPermissionGroupDefinitionAppService service) |
|||
{ |
|||
_service = service; |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Create)] |
|||
public virtual Task<PermissionGroupDefinitionDto> CreateAsync(PermissionGroupDefinitionCreateDto input) |
|||
{ |
|||
return _service.CreateAsync(input); |
|||
} |
|||
|
|||
[HttpDelete] |
|||
[Route("{name}")] |
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Delete)] |
|||
public virtual Task DeleteAsync(string name) |
|||
{ |
|||
return _service.DeleteAsync(name); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("{name}")] |
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Delete)] |
|||
public virtual Task<PermissionGroupDefinitionDto> GetAsync(string name) |
|||
{ |
|||
return _service.GetAsync(name); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public virtual Task<PagedResultDto<PermissionGroupDefinitionDto>> GetListAsync(PermissionGroupDefinitionGetListInput input) |
|||
{ |
|||
return _service.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("{name}")] |
|||
[Authorize(PermissionManagementPermissionNames.GroupDefinition.Update)] |
|||
public virtual Task<PermissionGroupDefinitionDto> UpdateAsync(string name, PermissionGroupDefinitionUpdateDto input) |
|||
{ |
|||
return _service.UpdateAsync(name, input); |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.PermissionManagement.Localization; |
|||
|
|||
namespace LINGYUN.Abp.PermissionManagement.HttpApi; |
|||
public abstract class PermissionManagementControllerBase : AbpControllerBase |
|||
{ |
|||
protected PermissionManagementControllerBase() |
|||
{ |
|||
LocalizationResource = typeof(AbpPermissionManagementResource); |
|||
} |
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
wwwroot |
|||
package*.json |
|||
@ -0,0 +1,9 @@ |
|||
"use strict"; |
|||
|
|||
var gulp = require("gulp"), |
|||
path = require('path'), |
|||
copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js'); |
|||
|
|||
exports.default = function(){ |
|||
return copyResources(path.resolve('./')); |
|||
}; |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue