Merge pull request #5062 from abpframework/cmskit-features

Implement basic Cmskit features & the global feature system
pull/5067/head
Halil İbrahim Kalkan 5 years ago committed by GitHub
commit 8e618df92c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -323,6 +323,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Aws",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Aws.Tests", "test\Volo.Abp.BlobStoring.Aws.Tests\Volo.Abp.BlobStoring.Aws.Tests.csproj", "{2CD3B26A-CA81-4279-8D5D-6A594517BB3F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.GlobalFeatures", "src\Volo.Abp.GlobalFeatures\Volo.Abp.GlobalFeatures.csproj", "{04F44063-C952-403A-815F-EFB778BDA125}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.GlobalFeatures.Tests", "test\Volo.Abp.GlobalFeatures.Tests\Volo.Abp.GlobalFeatures.Tests.csproj", "{231F1581-AA21-44C3-BF27-51EB3AD5355C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -961,6 +965,14 @@ Global
{2CD3B26A-CA81-4279-8D5D-6A594517BB3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CD3B26A-CA81-4279-8D5D-6A594517BB3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CD3B26A-CA81-4279-8D5D-6A594517BB3F}.Release|Any CPU.Build.0 = Release|Any CPU
{04F44063-C952-403A-815F-EFB778BDA125}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{04F44063-C952-403A-815F-EFB778BDA125}.Debug|Any CPU.Build.0 = Debug|Any CPU
{04F44063-C952-403A-815F-EFB778BDA125}.Release|Any CPU.ActiveCfg = Release|Any CPU
{04F44063-C952-403A-815F-EFB778BDA125}.Release|Any CPU.Build.0 = Release|Any CPU
{231F1581-AA21-44C3-BF27-51EB3AD5355C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{231F1581-AA21-44C3-BF27-51EB3AD5355C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{231F1581-AA21-44C3-BF27-51EB3AD5355C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{231F1581-AA21-44C3-BF27-51EB3AD5355C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1124,6 +1136,8 @@ Global
{8E49687A-E69F-49F2-8DB0-428D0883A937} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{50968CDE-1029-4051-B2E5-B69D0ECF2A18} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{2CD3B26A-CA81-4279-8D5D-6A594517BB3F} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{04F44063-C952-403A-815F-EFB778BDA125} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{231F1581-AA21-44C3-BF27-51EB3AD5355C} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

@ -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,3 @@
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("Volo.Abp.GlobalFeatures.Tests")]

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.GlobalFeatures</AssemblyName>
<PackageId>Volo.Abp.GlobalFeatures</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,9 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.GlobalFeatures
{
public class AbpGlobalFeaturesModule : AbpModule
{
}
}

@ -0,0 +1,51 @@
using JetBrains.Annotations;
namespace Volo.Abp.GlobalFeatures
{
public abstract class GlobalFeature
{
[NotNull]
public GlobalModuleFeatures Module { get; }
[NotNull]
public GlobalFeatureManager FeatureManager { get; }
[NotNull]
public string FeatureName { get; }
public bool IsEnabled
{
get => FeatureManager.IsEnabled(FeatureName);
set => SetEnabled(value);
}
protected GlobalFeature([NotNull] GlobalModuleFeatures module)
{
Module = Check.NotNull(module, nameof(module));
FeatureManager = Module.FeatureManager;
FeatureName = GlobalFeatureNameAttribute.GetName(GetType());
}
public virtual void Enable()
{
FeatureManager.Enable(FeatureName);
}
public virtual void Disable()
{
FeatureManager.Disable(FeatureName);
}
public void SetEnabled(bool isEnabled)
{
if (isEnabled)
{
Enable();
}
else
{
Disable();
}
}
}
}

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Volo.Abp.GlobalFeatures
{
public class GlobalFeatureDictionary : Dictionary<string, GlobalFeature>
{
}
}

@ -0,0 +1,53 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.GlobalFeatures
{
public class GlobalFeatureManager
{
public static GlobalFeatureManager Instance { get; protected set; } = new GlobalFeatureManager();
/// <summary>
/// A common dictionary to store arbitrary configurations.
/// </summary>
[NotNull]
public Dictionary<object, object> Configuration { get; }
public GlobalModuleFeaturesDictionary Modules { get; }
protected HashSet<string> EnabledFeatures { get; }
internal GlobalFeatureManager()
{
EnabledFeatures = new HashSet<string>();
Configuration = new Dictionary<object, object>();
Modules = new GlobalModuleFeaturesDictionary(this);
}
public virtual bool IsEnabled<TFeature>()
where TFeature : GlobalFeature
{
return IsEnabled(GlobalFeatureNameAttribute.GetName<TFeature>());
}
public virtual bool IsEnabled(string featureName)
{
return EnabledFeatures.Contains(featureName);
}
protected internal void Enable(string featureName)
{
EnabledFeatures.AddIfNotContains(featureName);
}
protected internal void Disable(string featureName)
{
EnabledFeatures.Remove(featureName);
}
public virtual IEnumerable<string> GetEnabledFeatureNames()
{
return EnabledFeatures;
}
}
}

@ -0,0 +1,42 @@
using System;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
namespace Volo.Abp.GlobalFeatures
{
[AttributeUsage(AttributeTargets.Class)]
public class GlobalFeatureNameAttribute : Attribute
{
[NotNull]
public string Name { get; }
public GlobalFeatureNameAttribute([NotNull] string name)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
}
public static string GetName<TFeature>()
where TFeature : GlobalFeature
{
return GetName(typeof(TFeature));
}
[NotNull]
public static string GetName(Type type)
{
var attribute = type
.GetCustomAttributes<GlobalFeatureNameAttribute>()
.FirstOrDefault();
if (attribute == null)
{
throw new AbpException($"{type.AssemblyQualifiedName} should define the {typeof(GlobalFeatureNameAttribute).FullName} atttribute!");
}
return attribute
.As<GlobalFeatureNameAttribute>()
.Name;
}
}
}

@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using JetBrains.Annotations;
namespace Volo.Abp.GlobalFeatures
{
public abstract class GlobalModuleFeatures
{
[NotNull]
public GlobalFeatureManager FeatureManager { get; }
[NotNull]
protected GlobalFeatureDictionary AllFeatures { get; }
protected GlobalModuleFeatures(
[NotNull] GlobalFeatureManager featureManager)
{
FeatureManager = Check.NotNull(featureManager, nameof(featureManager));
AllFeatures = new GlobalFeatureDictionary();
}
public virtual void Enable<TFeature>()
where TFeature : GlobalFeature
{
GetFeature<TFeature>().Enable();
}
public virtual void Disable<TFeature>()
where TFeature : GlobalFeature
{
GetFeature<TFeature>().Disable();
}
public virtual void SetEnabled<TFeature>(bool isEnabled)
where TFeature : GlobalFeature
{
GetFeature<TFeature>().SetEnabled(isEnabled);
}
public virtual void Enable(string featureName)
{
GetFeature(featureName).Enable();
}
public virtual void Disable(string featureName)
{
GetFeature(featureName).Disable();
}
public virtual void SetEnabled(string featureName, bool isEnabled)
{
GetFeature(featureName).SetEnabled(isEnabled);
}
public virtual void EnableAll()
{
foreach (var feature in AllFeatures.Values)
{
feature.Enable();
}
}
public virtual void DisableAll()
{
foreach (var feature in AllFeatures.Values)
{
feature.Disable();
}
}
public virtual GlobalFeature GetFeature(string featureName)
{
var feature = AllFeatures.GetOrDefault(featureName);
if (feature == null)
{
throw new AbpException($"There is no feature defined by name '{featureName}'.");
}
return feature;
}
public virtual TFeature GetFeature<TFeature>()
where TFeature : GlobalFeature
{
return (TFeature) GetFeature(GlobalFeatureNameAttribute.GetName<TFeature>());
}
public virtual IReadOnlyList<GlobalFeature> GetFeatures()
{
return AllFeatures.Values.ToImmutableList();
}
protected void AddFeature(GlobalFeature feature)
{
AllFeatures[feature.FeatureName] = feature;
}
}
}

@ -0,0 +1,16 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.GlobalFeatures
{
public class GlobalModuleFeaturesDictionary : Dictionary<string, GlobalModuleFeatures>
{
public GlobalFeatureManager FeatureManager { get; }
public GlobalModuleFeaturesDictionary(
[NotNull] GlobalFeatureManager featureManager)
{
FeatureManager = Check.NotNull(featureManager, nameof(featureManager));
}
}
}

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.GlobalFeatures\Volo.Abp.GlobalFeatures.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
</ItemGroup>
</Project>

@ -0,0 +1,23 @@
using Shouldly;
using Xunit;
namespace Volo.Abp.GlobalFeatures
{
public class GlobalFeatureManager_Tests
{
private readonly GlobalFeatureManager _featureManeger;
public GlobalFeatureManager_Tests()
{
_featureManeger = new GlobalFeatureManager();
}
[Fact]
public void Enable_Feature_By_Name()
{
_featureManeger.IsEnabled("Feature1").ShouldBeFalse();
_featureManeger.Enable("Feature1");
_featureManeger.IsEnabled("Feature1").ShouldBeTrue();
}
}
}

@ -0,0 +1,18 @@
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Threading;
namespace Volo.CmsKit
{
public static class FeatureConfigurer
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
GlobalFeatureManager.Instance.Modules.CmsKit().EnableAll();
});
}
}
}

@ -7,4 +7,8 @@
<RootNamespace>Volo.CmsKit</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.CmsKit.Domain.Shared\Volo.CmsKit.Domain.Shared.csproj" />
</ItemGroup>
</Project>

@ -52,6 +52,11 @@ namespace Volo.CmsKit
{
private const string DefaultCorsPolicyName = "Default";
public override void PreConfigureServices(ServiceConfigurationContext context)
{
FeatureConfigurer.Configure();
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
@ -163,7 +168,7 @@ namespace Volo.CmsKit
app.UseCorrelationId();
app.UseVirtualFiles();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName);
app.UseCors(DefaultCorsPolicyName);
app.UseAuthentication();
app.UseAbpClaimsMap();
if (MultiTenancyConsts.IsEnabled)

@ -9,6 +9,8 @@ namespace Volo.CmsKit.EntityFrameworkCore
{
public CmsKitHttpApiHostMigrationsDbContext CreateDbContext(string[] args)
{
FeatureConfigurer.Configure();
var configuration = BuildConfiguration();
var builder = new DbContextOptionsBuilder<CmsKitHttpApiHostMigrationsDbContext>()

@ -77,6 +77,11 @@ namespace Volo.CmsKit
{
private const string DefaultCorsPolicyName = "Default";
public override void PreConfigureServices(ServiceConfigurationContext context)
{
FeatureConfigurer.Configure();
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
@ -182,10 +187,10 @@ namespace Volo.CmsKit
app.UseCorrelationId();
app.UseVirtualFiles();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName);
app.UseCors(DefaultCorsPolicyName);
app.UseAuthentication();
app.UseJwtTokenMiddleware();
if (MultiTenancyConsts.IsEnabled)
{
app.UseMultiTenancy();

@ -9,6 +9,8 @@ namespace Volo.CmsKit.EntityFrameworkCore
{
public IdentityServerHostMigrationsDbContext CreateDbContext(string[] args)
{
FeatureConfigurer.Configure();
var configuration = BuildConfiguration();
var builder = new DbContextOptionsBuilder<IdentityServerHostMigrationsDbContext>()

@ -65,6 +65,8 @@ namespace Volo.CmsKit
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
FeatureConfigurer.Configure();
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(
@ -222,7 +224,7 @@ namespace Volo.CmsKit
app.UseHttpsRedirection();
app.UseVirtualFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthentication();
if (MultiTenancyConsts.IsEnabled)
{

@ -63,6 +63,11 @@ namespace Volo.CmsKit
)]
public class CmsKitWebUnifiedModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
FeatureConfigurer.Configure();
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();

@ -9,6 +9,8 @@ namespace Volo.CmsKit.EntityFrameworkCore
{
public UnifiedDbContext CreateDbContext(string[] args)
{
FeatureConfigurer.Configure();
var configuration = BuildConfiguration();
var builder = new DbContextOptionsBuilder<UnifiedDbContext>()

@ -11,6 +11,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Validation\Volo.Abp.Validation.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.GlobalFeatures\Volo.Abp.GlobalFeatures.csproj" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.6" />
</ItemGroup>

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.CmsKit.GlobalFeatures;
namespace Volo.Abp.GlobalFeatures
{
public static class GlobalModuleFeaturesDictionaryCmsKitExtensions
{
public static GlobalCmsKitFeatures CmsKit(
[NotNull] this GlobalModuleFeaturesDictionary modules)
{
Check.NotNull(modules, nameof(modules));
return modules
.GetOrAdd(
GlobalCmsKitFeatures.ModuleName,
_ => new GlobalCmsKitFeatures(modules.FeatureManager)
)
as GlobalCmsKitFeatures;
}
public static GlobalModuleFeaturesDictionary CmsKit(
[NotNull] this GlobalModuleFeaturesDictionary modules,
[NotNull] Action<GlobalCmsKitFeatures> configureAction)
{
Check.NotNull(configureAction, nameof(configureAction));
configureAction(modules.CmsKit());
return modules;
}
}
}

@ -1,4 +1,6 @@
using Volo.Abp.Modularity;
using System;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Modularity;
using Volo.Abp.Localization;
using Volo.CmsKit.Localization;
using Volo.Abp.Localization.ExceptionHandling;
@ -9,7 +11,8 @@ using Volo.Abp.VirtualFileSystem;
namespace Volo.CmsKit
{
[DependsOn(
typeof(AbpValidationModule)
typeof(AbpValidationModule),
typeof(AbpGlobalFeaturesModule)
)]
public class CmsKitDomainSharedModule : AbpModule
{

@ -0,0 +1,18 @@
using JetBrains.Annotations;
using Volo.Abp.GlobalFeatures;
namespace Volo.CmsKit.GlobalFeatures
{
[GlobalFeatureName(Name)]
public class CommentsFeature : GlobalFeature
{
public const string Name = "CmsKit.Comments";
internal CommentsFeature(
[NotNull] GlobalCmsKitFeatures cmsKit
) : base(cmsKit)
{
}
}
}

@ -0,0 +1,21 @@
using JetBrains.Annotations;
using Volo.Abp.GlobalFeatures;
namespace Volo.CmsKit.GlobalFeatures
{
public class GlobalCmsKitFeatures : GlobalModuleFeatures
{
public const string ModuleName = "CmsKit";
public ReactionsFeature Reactions => GetFeature<ReactionsFeature>();
public CommentsFeature Comments => GetFeature<CommentsFeature>();
public GlobalCmsKitFeatures([NotNull] GlobalFeatureManager featureManager)
: base(featureManager)
{
AddFeature(new ReactionsFeature(this));
AddFeature(new CommentsFeature(this));
}
}
}

@ -0,0 +1,17 @@
using JetBrains.Annotations;
using Volo.Abp.GlobalFeatures;
namespace Volo.CmsKit.GlobalFeatures
{
[GlobalFeatureName(Name)]
public class ReactionsFeature : GlobalFeature
{
public const string Name = "CmsKit.Reactions";
internal ReactionsFeature(
[NotNull] GlobalCmsKitFeatures cmsKit
) : base(cmsKit)
{
}
}
}

@ -8,6 +8,7 @@ using Volo.Abp;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.EntityFrameworkCore;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Comments
{
@ -27,7 +28,7 @@ namespace Volo.CmsKit.Comments
Check.NotNullOrWhiteSpace(entityId, nameof(entityId));
var query = from comment in DbSet
join user in DbContext.CmsUsers on comment.CreatorId equals user.Id
join user in DbContext.Set<CmsUser>() on comment.CreatorId equals user.Id
where entityType == comment.EntityType && entityId == comment.EntityId
orderby comment.CreationTime
select new CommentWithAuthorQueryResultItem

@ -1,21 +1,12 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.EntityFrameworkCore
{
[ConnectionStringName(CmsKitDbProperties.ConnectionStringName)]
public class CmsKitDbContext : AbpDbContext<CmsKitDbContext>, ICmsKitDbContext
{
public DbSet<UserReaction> UserReactions { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<CmsUser> CmsUsers { get; set; }
public CmsKitDbContext(DbContextOptions<CmsKitDbContext> options)
: base(options)
{

@ -2,10 +2,12 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Users;
using Volo.Abp.Users.EntityFrameworkCore;
using Volo.CmsKit.GlobalFeatures;
namespace Volo.CmsKit.EntityFrameworkCore
{
@ -32,34 +34,40 @@ namespace Volo.CmsKit.EntityFrameworkCore
b.ConfigureAbpUser();
});
builder.Entity<UserReaction>(b =>
if (GlobalFeatureManager.Instance.IsEnabled<ReactionsFeature>())
{
b.ToTable(options.TablePrefix + "UserReactions", options.Schema);
b.ConfigureByConvention();
builder.Entity<UserReaction>(b =>
{
b.ToTable(options.TablePrefix + "UserReactions", options.Schema);
b.ConfigureByConvention();
b.Property(x => x.EntityType).IsRequired().HasMaxLength(UserReactionConsts.MaxEntityTypeLength);
b.Property(x => x.EntityId).IsRequired().HasMaxLength(UserReactionConsts.MaxEntityIdLength);
b.Property(x => x.ReactionName).IsRequired().HasMaxLength(UserReactionConsts.MaxReactionNameLength);
b.Property(x => x.CreationTime);
b.Property(x => x.EntityType).IsRequired().HasMaxLength(UserReactionConsts.MaxEntityTypeLength);
b.Property(x => x.EntityId).IsRequired().HasMaxLength(UserReactionConsts.MaxEntityIdLength);
b.Property(x => x.ReactionName).IsRequired().HasMaxLength(UserReactionConsts.MaxReactionNameLength);
b.Property(x => x.CreationTime);
b.HasIndex(x => new { x.EntityType, x.EntityId });
b.HasIndex(x => new { x.CreatorId, x.EntityType, x.EntityId, x.ReactionName });
});
b.HasIndex(x => new { x.EntityType, x.EntityId });
b.HasIndex(x => new { x.CreatorId, x.EntityType, x.EntityId, x.ReactionName });
});
}
builder.Entity<Comment>(b =>
if (GlobalFeatureManager.Instance.IsEnabled<CommentsFeature>())
{
b.ToTable(options.TablePrefix + "Comments", options.Schema);
b.ConfigureByConvention();
builder.Entity<Comment>(b =>
{
b.ToTable(options.TablePrefix + "Comments", options.Schema);
b.ConfigureByConvention();
b.Property(x => x.EntityType).IsRequired().HasMaxLength(CommentConsts.MaxEntityTypeLength);
b.Property(x => x.EntityId).IsRequired().HasMaxLength(CommentConsts.MaxEntityIdLength);
b.Property(x => x.Text).IsRequired().HasMaxLength(CommentConsts.MaxTextLength);
b.Property(x => x.RepliedCommentId);
b.Property(x => x.CreationTime);
b.Property(x => x.EntityType).IsRequired().HasMaxLength(CommentConsts.MaxEntityTypeLength);
b.Property(x => x.EntityId).IsRequired().HasMaxLength(CommentConsts.MaxEntityIdLength);
b.Property(x => x.Text).IsRequired().HasMaxLength(CommentConsts.MaxTextLength);
b.Property(x => x.RepliedCommentId);
b.Property(x => x.CreationTime);
b.HasIndex(x => new { x.EntityType, x.EntityId });
b.HasIndex(x => new { x.RepliedCommentId });
});
b.HasIndex(x => new { x.EntityType, x.EntityId });
b.HasIndex(x => new { x.RepliedCommentId });
});
}
}
}
}

@ -1,19 +1,10 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.EntityFrameworkCore
{
[ConnectionStringName(CmsKitDbProperties.ConnectionStringName)]
public interface ICmsKitDbContext : IEfCoreDbContext
{
DbSet<UserReaction> UserReactions { get; }
DbSet<Comment> Comments { get; }
DbSet<CmsUser> CmsUsers { get; set; }
}
}

@ -1,11 +1,8 @@
using System;
using System.Linq;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using Shouldly;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Users;
using Volo.CmsKit.Public.Comments;
using Xunit;
@ -54,7 +51,7 @@ namespace Volo.CmsKit.Comments
UsingDbContext(context =>
{
var comments = context.Comments.Where(x =>
var comments = context.Set<Comment>().Where(x =>
x.EntityId == _cmsKitTestData.EntityId1 && x.EntityType == _cmsKitTestData.EntityType1).ToList();
comments
@ -75,7 +72,7 @@ namespace Volo.CmsKit.Comments
UsingDbContext(context =>
{
var comment = context.Comments.Single(x =>
var comment = context.Set<Comment>().Single(x =>
x.Id == _cmsKitTestData.CommentWithChildId);
comment.Text.ShouldBe("I'm Updated");
@ -91,7 +88,7 @@ namespace Volo.CmsKit.Comments
UsingDbContext(context =>
{
var comment = context.Comments.FirstOrDefault(x =>
var comment = context.Set<Comment>().FirstOrDefault(x =>
x.Id == _cmsKitTestData.CommentWithChildId);
comment.ShouldBeNull();

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
@ -69,7 +66,7 @@ namespace Volo.CmsKit.Reactions
UsingDbContext(context =>
{
var reaction = context.UserReactions.FirstOrDefault(x =>
var reaction = context.Set<UserReaction>().FirstOrDefault(x =>
x.CreatorId == _cmsKitTestData.User1Id &&
x.ReactionName == StandardReactions.Hooray &&
x.EntityId == _cmsKitTestData.EntityId2 &&
@ -93,7 +90,7 @@ namespace Volo.CmsKit.Reactions
UsingDbContext(context =>
{
var reaction = context.UserReactions.FirstOrDefault(x =>
var reaction = context.Set<UserReaction>().FirstOrDefault(x =>
x.CreatorId == _cmsKitTestData.User1Id &&
x.ReactionName == StandardReactions.Confused &&
x.EntityId == _cmsKitTestData.EntityId1 &&

@ -69,7 +69,7 @@ namespace Volo.CmsKit.Reactions
UsingDbContext(context =>
{
var reaction = context.UserReactions.FirstOrDefault(x =>
var reaction = context.Set<UserReaction>().FirstOrDefault(x =>
x.CreatorId == _cmsKitTestData.User1Id &&
x.ReactionName == StandardReactions.Confused &&
x.EntityId == _cmsKitTestData.EntityId1 &&

@ -1,7 +1,9 @@
using Volo.CmsKit.Comments;
using Xunit;
namespace Volo.CmsKit.MongoDB.Comments
{
[Collection(MongoTestCollection.Name)]
public class CommentRepository_Tests : CommentRepository_Tests<CmsKitMongoDbTestModule>
{

@ -1,7 +1,9 @@
using Volo.CmsKit.Reactions;
using Xunit;
namespace Volo.CmsKit.MongoDB.Reactions
{
[Collection(MongoTestCollection.Name)]
public class UserReactionRepository_Tests : UserReactionRepository_Tests<CmsKitMongoDbTestModule>
{
}

@ -3,6 +3,7 @@ using Volo.Abp;
using Volo.Abp.Authorization;
using Volo.Abp.Autofac;
using Volo.Abp.Data;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
@ -16,8 +17,15 @@ namespace Volo.CmsKit
)]
public class CmsKitTestBaseModule : AbpModule
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public override void ConfigureServices(ServiceConfigurationContext context)
{
OneTimeRunner.Run(() =>
{
GlobalFeatureManager.Instance.Modules.CmsKit().EnableAll();
});
context.Services.AddAlwaysAllowAuthorization();
}

@ -86,6 +86,7 @@ $projects = (
"framework/src/Volo.Abp.EventBus.RabbitMQ",
"framework/src/Volo.Abp.Features",
"framework/src/Volo.Abp.FluentValidation",
"framework/src/Volo.Abp.GlobalFeatures",
"framework/src/Volo.Abp.Guids",
"framework/src/Volo.Abp.HangFire",
"framework/src/Volo.Abp.Http.Abstractions",

Loading…
Cancel
Save