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