Commit 4d8a5451 authored by Super's avatar Super

Finish basic functions.

parent 45e15216
......@@ -10,6 +10,7 @@ using Swashbuckle.AspNetCore.Swagger;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Serilog;
......@@ -106,6 +107,19 @@ namespace EasyAbp.CacheManagement
{
options.IsEnabled = MultiTenancyConsts.IsEnabled;
});
ConfigureConventionalControllers();
}
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(CacheManagementApplicationModule).Assembly, setting =>
{
setting.RootPath = "cacheManagement";
});
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
......
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace EasyAbp.CacheManagement.Migrations
{
public partial class AddedCacheItem : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "CacheManagementCacheItems",
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
ExtraProperties = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
FullTypeName = table.Column<string>(nullable: true),
DisplayName = table.Column<string>(nullable: true),
Description = table.Column<string>(nullable: true),
TenantAllowed = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CacheManagementCacheItems", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CacheManagementCacheItems");
}
}
}
// <auto-generated />
using System;
using EasyAbp.CacheManagement.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using EasyAbp.CacheManagement.EntityFrameworkCore;
namespace EasyAbp.CacheManagement.Migrations
{
......@@ -19,6 +19,38 @@ namespace EasyAbp.CacheManagement.Migrations
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("EasyAbp.CacheManagement.CacheItems.CacheItem", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnName("ConcurrencyStamp")
.HasColumnType("nvarchar(max)");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("ExtraProperties")
.HasColumnName("ExtraProperties")
.HasColumnType("nvarchar(max)");
b.Property<string>("FullTypeName")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TenantAllowed")
.HasColumnType("bit");
b.HasKey("Id");
b.ToTable("CacheManagementCacheItems");
});
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
{
b.Property<Guid>("Id")
......
......@@ -8,7 +8,13 @@ namespace EasyAbp.CacheManagement.Authorization
{
public override void Define(IPermissionDefinitionContext context)
{
//var moduleGroup = context.AddGroup(CacheManagementPermissions.GroupName, L("Permission:CacheManagement"));
var moduleGroup = context.AddGroup(CacheManagementPermissions.GroupName, L("Permission:CacheManagement"));
var cacheItems = moduleGroup.AddPermission(CacheManagementPermissions.CacheItems.Default, L("Permission:CacheItem"));
cacheItems.AddChild(CacheManagementPermissions.CacheItems.Create, L("Permission:Create"));
cacheItems.AddChild(CacheManagementPermissions.CacheItems.Update, L("Permission:SetRead"));
cacheItems.AddChild(CacheManagementPermissions.CacheItems.Delete, L("Permission:Delete"));
cacheItems.AddChild(CacheManagementPermissions.CacheItems.ClearCache, L("Permission:ClearCache"));
}
private static LocalizableString L(string name)
......
......@@ -5,6 +5,15 @@ namespace EasyAbp.CacheManagement.Authorization
public class CacheManagementPermissions
{
public const string GroupName = "CacheManagement";
public class CacheItems
{
public const string Default = GroupName + ".CacheItem";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
public const string ClearCache = Default + ".ClearCache";
}
public static string[] GetAll()
{
......
using System;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.CacheManagement.CacheItems.Dtos
{
public class CacheItemDto : EntityDto<Guid>
{
public string FullTypeName { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public bool TenantAllowed { get; set; }
}
}
\ No newline at end of file
using System;
using System.ComponentModel;
namespace EasyAbp.CacheManagement.CacheItems.Dtos
{
public class ClearAllCacheItemDto
{
[DisplayName("CacheItemId")]
public Guid CacheItemId { get; set; }
}
}
\ No newline at end of file
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace EasyAbp.CacheManagement.CacheItems.Dtos
{
public class ClearCacheItemDto
{
[DisplayName("CacheItemId")]
public Guid CacheItemId { get; set; }
[Required]
[DisplayName("CacheItemCacheKey")]
public string CacheKey { get; set; }
}
}
\ No newline at end of file
using System;
namespace EasyAbp.CacheManagement.CacheItems.Dtos
{
public class ClearCacheItemResultDto
{
public Guid CacheItemId { get; set; }
public long Count { get; set; }
}
}
\ No newline at end of file
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace EasyAbp.CacheManagement.CacheItems.Dtos
{
public class CreateUpdateCacheItemDto
{
[Required]
[DisplayName("CacheItemFullTypeName")]
public string FullTypeName { get; set; }
[Required]
[DisplayName("CacheItemDisplayName")]
public string DisplayName { get; set; }
[DisplayName("CacheItemDescription")]
public string Description { get; set; }
[DisplayName("CacheItemTenantAllowed")]
public bool TenantAllowed { get; set; }
}
}
\ No newline at end of file
using System;
using System.Threading.Tasks;
using EasyAbp.CacheManagement.CacheItems.Dtos;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace EasyAbp.CacheManagement.CacheItems
{
public interface ICacheItemAppService :
ICrudAppService<
CacheItemDto,
Guid,
PagedAndSortedResultRequestDto,
CreateUpdateCacheItemDto,
CreateUpdateCacheItemDto>
{
Task<ClearCacheItemResultDto> ClearAsync(ClearCacheItemDto input);
Task<ClearCacheItemResultDto> ClearAllAsync(ClearAllCacheItemDto input);
}
}
\ No newline at end of file
using System;
using System.Threading.Tasks;
using EasyAbp.CacheManagement.Authorization;
using EasyAbp.CacheManagement.CacheItems.Dtos;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.MultiTenancy;
namespace EasyAbp.CacheManagement.CacheItems
{
public class CacheItemAppService : CrudAppService<CacheItem, CacheItemDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateCacheItemDto, CreateUpdateCacheItemDto>,
ICacheItemAppService
{
protected override string CreatePolicyName { get; set; } = CacheManagementPermissions.CacheItems.Create;
protected override string DeletePolicyName { get; set; } = CacheManagementPermissions.CacheItems.Delete;
protected override string UpdatePolicyName { get; set; } = CacheManagementPermissions.CacheItems.Update;
protected override string GetPolicyName { get; set; } = CacheManagementPermissions.CacheItems.Default;
protected override string GetListPolicyName { get; set; } = CacheManagementPermissions.CacheItems.Default;
private readonly ICacheItemManager _cacheItemManager;
private readonly ICacheItemRepository _repository;
public CacheItemAppService(
ICacheItemManager cacheItemManager,
ICacheItemRepository repository) : base(repository)
{
_cacheItemManager = cacheItemManager;
_repository = repository;
}
[Authorize(CacheManagementPermissions.CacheItems.ClearCache)]
public async Task<ClearCacheItemResultDto> ClearAsync(ClearCacheItemDto input)
{
var cacheItem = await _repository.GetAsync(input.CacheItemId);
await AuthorizationService.CheckAsync(cacheItem, CacheManagementPermissions.CacheItems.ClearCache);
await _cacheItemManager.ClearAsync(cacheItem, input.CacheKey);
return new ClearCacheItemResultDto
{
CacheItemId = cacheItem.Id,
Count = 1
};
}
public async Task<ClearCacheItemResultDto> ClearAllAsync(ClearAllCacheItemDto input)
{
throw new NotImplementedException();
}
}
}
\ No newline at end of file
using System.Threading.Tasks;
using EasyAbp.CacheManagement.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Volo.Abp.MultiTenancy;
namespace EasyAbp.CacheManagement.CacheItems
{
public class CacheItemAuthorizationHandler : AuthorizationHandler<OperationAuthorizationRequirement, CacheItem>
{
private readonly ICurrentTenant _currentTenant;
public CacheItemAuthorizationHandler(
ICurrentTenant currentTenant)
{
_currentTenant = currentTenant;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
OperationAuthorizationRequirement requirement, CacheItem resource)
{
if (requirement.Name.Equals(CacheManagementPermissions.CacheItems.ClearCache) &&
HasClearCachePermission(context, resource))
{
context.Succeed(requirement);
return Task.CompletedTask;
}
return Task.CompletedTask;
}
private bool HasClearCachePermission(AuthorizationHandlerContext context, CacheItem resource)
{
return resource.TenantAllowed || _currentTenant.GetMultiTenancySide() == MultiTenancySides.Host;
}
}
}
\ No newline at end of file
using AutoMapper;
using EasyAbp.CacheManagement.CacheItems;
using EasyAbp.CacheManagement.CacheItems.Dtos;
using AutoMapper;
namespace EasyAbp.CacheManagement
{
......@@ -9,6 +11,8 @@ namespace EasyAbp.CacheManagement
/* You can configure your AutoMapper mapping configuration here.
* Alternatively, you can split your mapping configurations
* into multiple profile classes for a better organization. */
CreateMap<CacheItem, CacheItemDto>();
CreateMap<CreateUpdateCacheItemDto, CacheItem>(MemberList.Source);
}
}
}
\ No newline at end of file
}
......@@ -12,15 +12,6 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\cs.json" />
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\en.json" />
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\pl.json" />
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\pt-BR.json" />
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\sl.json" />
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\tr.json" />
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\vi.json" />
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\zh-Hans.json" />
<EmbeddedResource Include="EasyAbp\CacheManagement\Localization\CacheManagement\zh-Hant.json" />
<EmbeddedResource Include="Localization\CacheManagement\*.json" />
<Content Remove="Localization\CacheManagement\*.json" />
</ItemGroup>
......
{
"culture": "cs",
"texts": {
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
\ No newline at end of file
{
"culture": "en",
"texts": {
"ManageYourProfile": "Manage your profile"
"ManageYourProfile": "Manage your profile",
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
\ No newline at end of file
{
"culture": "pl",
"texts": {
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
\ No newline at end of file
{
"culture": "pt-BR",
"texts": {
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
\ No newline at end of file
{
"culture": "sl",
"texts": {
"ManageYourProfile": "Upravljajte svojim profilom"
"ManageYourProfile": "Upravljajte svojim profilom",
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
\ No newline at end of file
{
"culture": "tr",
"texts": {
"ManageYourProfile": "Profil ynetimi"
"ManageYourProfile": "Profil y�netimi",
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
\ No newline at end of file
{
"culture": "vi",
"texts": {
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
}
\ No newline at end of file
{
"culture": "zh-Hans",
"texts": {
"ManageYourProfile": "管理个人资料"
"ManageYourProfile": "管理个人资料",
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
\ No newline at end of file
{
"culture": "zh-Hant",
"texts": {
"ManageYourProfile": "管理個人資料"
"ManageYourProfile": "管理個人資料",
"Menu:CacheItem": "MenuCacheItem",
"CacheItem": "CacheItem",
"CacheItemFullTypeName": "CacheItemFullTypeName",
"CacheItemDisplayName": "CacheItemDisplayName",
"CacheItemDescription": "CacheItemDescription",
"CacheItemTenantAllowed": "CacheItemTenantAllowed",
"CreateCacheItem": "CreateCacheItem",
"EditCacheItem": "EditCacheItem",
"CacheItemDeletionConfirmationMessage": "Are you sure to delete the cacheitem {0}?",
"SuccessfullyDeleted": "Successfully deleted"
}
}
\ No newline at end of file
......@@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Caching" Version="2.3.0" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="2.3.0" />
<ProjectReference Include="..\EasyAbp.CacheManagement.Domain.Shared\EasyAbp.CacheManagement.Domain.Shared.csproj" />
</ItemGroup>
......
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace EasyAbp.CacheManagement.CacheItems
{
public class CacheItem : AggregateRoot<Guid>
{
[NotNull]
public virtual string FullTypeName { get; protected set; }
[NotNull]
public virtual string DisplayName { get; protected set; }
[CanBeNull]
public virtual string Description { get; protected set; }
public virtual bool TenantAllowed { get; protected set; }
protected CacheItem()
{
}
public CacheItem(
Guid id,
[NotNull] string fullTypeName,
[NotNull] string displayName,
[CanBeNull] string description,
bool tenantAllowed
) :base(id)
{
FullTypeName = fullTypeName;
DisplayName = displayName;
Description = description;
TenantAllowed = tenantAllowed;
}
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Services;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
namespace EasyAbp.CacheManagement.CacheItems
{
public class CacheItemManager : DomainService, ICacheItemManager
{
private readonly IDistributedCache _distributedCache;
private readonly ICancellationTokenProvider _cancellationTokenProvider;
private readonly IDistributedCacheKeyNormalizer _keyNormalizer;
public CacheItemManager(
IDistributedCache distributedCache,
ICancellationTokenProvider cancellationTokenProvider,
IDistributedCacheKeyNormalizer keyNormalizer)
{
_distributedCache = distributedCache;
_cancellationTokenProvider = cancellationTokenProvider;
_keyNormalizer = keyNormalizer;
}
public async Task ClearAsync(CacheItem cacheItem, string cacheKey, CancellationToken cancellationToken = default)
{
var type = Type.GetType(cacheItem.FullTypeName);
if (type == null)
{
throw new CacheItemTypeNotFoundException(cacheItem.FullTypeName);
}
var normalizedKey = _keyNormalizer.NormalizeKey(
new DistributedCacheKeyNormalizeArgs(
cacheKey,
CacheNameAttribute.GetCacheName(type),
type.IsDefined(typeof(IgnoreMultiTenancyAttribute), true)
)
);
await _distributedCache.RemoveAsync(normalizedKey, _cancellationTokenProvider.FallbackToProvider());
}
}
}
\ No newline at end of file
using Volo.Abp;
namespace EasyAbp.CacheManagement.CacheItems
{
public class CacheItemTypeNotFoundException : BusinessException
{
public CacheItemTypeNotFoundException(string typeName) : base(message: $"Cache item type not found: {typeName}")
{
}
}
}
\ No newline at end of file
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
namespace EasyAbp.CacheManagement.CacheItems
{
public interface ICacheItemManager : IDomainService
{
Task ClearAsync(CacheItem cacheItem, string cacheKey, CancellationToken cancellationToken = default);
}
}
\ No newline at end of file
using System;
using Volo.Abp.Domain.Repositories;
namespace EasyAbp.CacheManagement.CacheItems
{
public interface ICacheItemRepository : IRepository<CacheItem, Guid>
{
}
}
\ No newline at end of file
using System;
using EasyAbp.CacheManagement.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace EasyAbp.CacheManagement.CacheItems
{
public class CacheItemRepository : EfCoreRepository<CacheManagementDbContext, CacheItem, Guid>, ICacheItemRepository
{
public CacheItemRepository(IDbContextProvider<CacheManagementDbContext> dbContextProvider) : base(dbContextProvider)
{
}
}
}
\ No newline at end of file
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using EasyAbp.CacheManagement.CacheItems;
namespace EasyAbp.CacheManagement.EntityFrameworkCore
{
......@@ -10,6 +11,7 @@ namespace EasyAbp.CacheManagement.EntityFrameworkCore
/* Add DbSet for each Aggregate Root here. Example:
* public DbSet<Question> Questions { get; set; }
*/
public DbSet<CacheItem> CacheItems { get; set; }
public CacheManagementDbContext(DbContextOptions<CacheManagementDbContext> options)
: base(options)
......@@ -24,4 +26,4 @@ namespace EasyAbp.CacheManagement.EntityFrameworkCore
builder.ConfigureCacheManagement();
}
}
}
\ No newline at end of file
}
using System;
using EasyAbp.CacheManagement.CacheItems;
using System;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace EasyAbp.CacheManagement.EntityFrameworkCore
{
......@@ -38,6 +40,13 @@ namespace EasyAbp.CacheManagement.EntityFrameworkCore
b.HasIndex(q => q.CreationTime);
});
*/
builder.Entity<CacheItem>(b =>
{
b.ToTable(options.TablePrefix + "CacheItems", options.Schema);
b.ConfigureByConvention();
/* Configure more properties here */
});
}
}
}
\ No newline at end of file
}
using Microsoft.Extensions.DependencyInjection;
using EasyAbp.CacheManagement.CacheItems;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
......@@ -17,7 +18,8 @@ namespace EasyAbp.CacheManagement.EntityFrameworkCore
/* Add custom repositories here. Example:
* options.AddRepository<Question, EfCoreQuestionRepository>();
*/
options.AddRepository<CacheItem, CacheItemRepository>();
});
}
}
}
\ No newline at end of file
}
using Volo.Abp.Data;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using EasyAbp.CacheManagement.CacheItems;
namespace EasyAbp.CacheManagement.EntityFrameworkCore
{
......@@ -9,5 +11,6 @@ namespace EasyAbp.CacheManagement.EntityFrameworkCore
/* Add DbSet for each Aggregate Root here. Example:
* DbSet<Question> Questions { get; }
*/
DbSet<CacheItem> CacheItems { get; set; }
}
}
\ No newline at end of file
}
using System.Threading.Tasks;
using EasyAbp.CacheManagement.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using EasyAbp.CacheManagement.Localization;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.UI.Navigation;
namespace EasyAbp.CacheManagement.Web
......@@ -13,11 +18,18 @@ namespace EasyAbp.CacheManagement.Web
}
}
private Task ConfigureMainMenu(MenuConfigurationContext context)
private async Task ConfigureMainMenu(MenuConfigurationContext context)
{
//Add main menu items.
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<CacheManagementResource>>();
return Task.CompletedTask;
var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>();
if (await authorizationService.IsGrantedAsync(CacheManagementPermissions.CacheItems.Default))
{
context.Menu.AddItem(
new ApplicationMenuItem("CacheItem", l["Menu:CacheItem"], "/CacheManagement/CacheItems/CacheItem")
);
}
}
}
}
\ No newline at end of file
}
using AutoMapper;
using EasyAbp.CacheManagement.CacheItems.Dtos;
using AutoMapper;
using EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.ViewModels;
namespace EasyAbp.CacheManagement.Web
{
......@@ -9,6 +11,8 @@ namespace EasyAbp.CacheManagement.Web
/* You can configure your AutoMapper mapping configuration here.
* Alternatively, you can split your mapping configurations
* into multiple profile classes for a better organization. */
CreateMap<CacheItemDto, CreateEditCacheItemViewModel>();
CreateMap<CreateEditCacheItemViewModel, CreateUpdateCacheItemDto>();
}
}
}
\ No newline at end of file
}
......@@ -36,7 +36,17 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Pages\CacheManagement\CacheItems" />
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<_ContentIncludedByDefault Remove="Pages\CacheItems\CacheItem\CreateModal.cshtml" />
<_ContentIncludedByDefault Remove="Pages\CacheItems\CacheItem\EditModal.cshtml" />
<_ContentIncludedByDefault Remove="Pages\CacheItems\CacheItem\Index.cshtml" />
<_ContentIncludedByDefault Remove="Pages\CacheManagement\CacheItems\CacheItem\CreateModal.cshtml" />
<_ContentIncludedByDefault Remove="Pages\CacheManagement\CacheItems\CacheItem\EditModal.cshtml" />
<_ContentIncludedByDefault Remove="Pages\CacheManagement\CacheItems\CacheItem\Index.cshtml" />
</ItemGroup>
</Project>
@page
@inherits EasyAbp.CacheManagement.Web.Pages.CacheManagementPage
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@model EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.ClearCacheModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="ViewModel" data-ajaxForm="true" asp-page="ClearCacheModal">
<abp-modal>
<abp-modal-header title="@L["ClearCacheCacheItem"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="CacheItemId" />
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>
\ No newline at end of file
using System;
using System.Threading.Tasks;
using EasyAbp.CacheManagement.CacheItems;
using EasyAbp.CacheManagement.CacheItems.Dtos;
using EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.ViewModels;
using Microsoft.AspNetCore.Mvc;
namespace EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem
{
public class ClearCacheModalModel : CacheManagementPageModel
{
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid CacheItemId { get; set; }
[BindProperty]
public ClearCacheItemViewModel ViewModel { get; set; }
private readonly ICacheItemAppService _service;
public ClearCacheModalModel(ICacheItemAppService service)
{
_service = service;
}
public async Task<IActionResult> OnPostAsync()
{
await _service.ClearAsync(new ClearCacheItemDto
{
CacheItemId = CacheItemId,
CacheKey = ViewModel.CacheKey
});
return NoContent();
}
}
}
\ No newline at end of file
@page
@inherits EasyAbp.CacheManagement.Web.Pages.CacheManagementPage
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@model EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.CreateModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="CacheItem" data-ajaxForm="true" asp-page="CreateModal">
<abp-modal>
<abp-modal-header title="@L["CreateCacheItem"].Value"></abp-modal-header>
<abp-modal-body>
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>
\ No newline at end of file
using System.Threading.Tasks;
using EasyAbp.CacheManagement.CacheItems;
using EasyAbp.CacheManagement.CacheItems.Dtos;
using EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.ViewModels;
using Microsoft.AspNetCore.Mvc;
namespace EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem
{
public class CreateModalModel : CacheManagementPageModel
{
[BindProperty]
public CreateEditCacheItemViewModel CacheItem { get; set; }
private readonly ICacheItemAppService _service;
public CreateModalModel(ICacheItemAppService service)
{
_service = service;
}
public async Task<IActionResult> OnPostAsync()
{
await _service.CreateAsync(
ObjectMapper.Map<CreateEditCacheItemViewModel, CreateUpdateCacheItemDto>(CacheItem));
return NoContent();
}
}
}
\ No newline at end of file
@page
@inherits EasyAbp.CacheManagement.Web.Pages.CacheManagementPage
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@model EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.EditModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="CacheItem" data-ajaxForm="true" asp-page="EditModal">
<abp-modal>
<abp-modal-header title="@L["EditCacheItem"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Id" />
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>
\ No newline at end of file
using System;
using System.Threading.Tasks;
using EasyAbp.CacheManagement.CacheItems;
using EasyAbp.CacheManagement.CacheItems.Dtos;
using EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.ViewModels;
using Microsoft.AspNetCore.Mvc;
namespace EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem
{
public class EditModalModel : CacheManagementPageModel
{
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid Id { get; set; }
[BindProperty]
public CreateEditCacheItemViewModel CacheItem { get; set; }
private readonly ICacheItemAppService _service;
public EditModalModel(ICacheItemAppService service)
{
_service = service;
}
public async Task OnGetAsync()
{
var dto = await _service.GetAsync(Id);
CacheItem = ObjectMapper.Map<CacheItemDto, CreateEditCacheItemViewModel>(dto);
}
public async Task<IActionResult> OnPostAsync()
{
await _service.UpdateAsync(Id,
ObjectMapper.Map<CreateEditCacheItemViewModel, CreateUpdateCacheItemDto>(CacheItem));
return NoContent();
}
}
}
\ No newline at end of file
@page
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@inherits EasyAbp.CacheManagement.Web.Pages.CacheManagementPage
@model EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.IndexModel
@inject IPageLayout PageLayout
@{
PageLayout.Content.Title = L["CacheItem"].Value;
PageLayout.Content.BreadCrumb.Add(L["Menu:CacheItem"].Value);
PageLayout.Content.MenuItemName = "CacheItem";
}
@section scripts
{
<abp-script src="/Pages/CacheManagement/CacheItems/CacheItem/index.js" />
}
@section styles
{
<abp-style src="/Pages/CacheManagement/CacheItems/CacheItem/index.css"/>
}
<abp-card>
<abp-card-header>
<abp-row>
<abp-column size-md="_6">
<abp-card-title>@L["CacheItem"]</abp-card-title>
</abp-column>
<abp-column size-md="_6" class="text-right">
<abp-button id="NewCacheItemButton"
text="@L["CreateCacheItem"].Value"
icon="plus"
button-type="Primary" />
</abp-column>
</abp-row>
</abp-card-header>
<abp-card-body>
<abp-table striped-rows="true" id="CacheItemTable" class="nowrap">
<thead>
<tr>
<th>@L["Actions"]</th>
<th>@L["CacheItemDisplayName"]</th>
<th>@L["CacheItemDescription"]</th>
</tr>
</thead>
</abp-table>
</abp-card-body>
</abp-card>
\ No newline at end of file
using System.Threading.Tasks;
namespace EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem
{
public class IndexModel : CacheManagementPageModel
{
public async Task OnGetAsync()
{
await Task.CompletedTask;
}
}
}
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.ViewModels
{
public class ClearCacheItemViewModel
{
[Required]
[DisplayName("CacheItemCacheKey")]
public string CacheKey { get; set; }
}
}
\ No newline at end of file
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace EasyAbp.CacheManagement.Web.Pages.CacheManagement.CacheItems.CacheItem.ViewModels
{
public class CreateEditCacheItemViewModel
{
[Required]
[DisplayName("CacheItemFullTypeName")]
public string FullTypeName { get; set; }
[Required]
[DisplayName("CacheItemDisplayName")]
public string DisplayName { get; set; }
[DisplayName("CacheItemDescription")]
[TextArea(Rows = 4)]
public string Description { get; set; }
[DisplayName("CacheItemTenantAllowed")]
public bool TenantAllowed { get; set; }
}
}
\ No newline at end of file
$(function () {
var l = abp.localization.getResource('CacheManagement');
var service = easyAbp.cacheManagement.cacheItems.cacheItem;
var createModal = new abp.ModalManager(abp.appPath + 'CacheManagement/CacheItems/CacheItem/CreateModal');
var editModal = new abp.ModalManager(abp.appPath + 'CacheManagement/CacheItems/CacheItem/EditModal');
var clearCacheModal = new abp.ModalManager(abp.appPath + 'CacheManagement/CacheItems/CacheItem/ClearCacheModal');
var dataTable = $('#CacheItemTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
order: [[1, "asc"]],
ajax: abp.libs.datatables.createAjax(service.getList),
columnDefs: [
{
rowAction: {
items:
[
{
text: l('ClearCache'),
action: function (data) {
clearCacheModal.open({ cacheItemId: data.record.id });
}
},
{
text: l('Edit'),
action: function (data) {
editModal.open({ id: data.record.id });
}
},
{
text: l('Delete'),
confirmMessage: function (data) {
return l('CacheItemDeletionConfirmationMessage', data.record.id);
},
action: function (data) {
service.delete(data.record.id)
.then(function () {
abp.notify.info(l('SuccessfullyDeleted'));
dataTable.ajax.reload();
});
}
}
]
}
},
{ data: "displayName" },
{ data: "description" },
]
}));
createModal.onResult(function () {
dataTable.ajax.reload();
});
editModal.onResult(function () {
dataTable.ajax.reload();
});
clearCacheModal.onResult(function () {
dataTable.ajax.reload();
});
$('#NewCacheItemButton').click(function (e) {
e.preventDefault();
createModal.open();
});
});
\ No newline at end of file
using Shouldly;
using System.Threading.Tasks;
using Xunit;
namespace EasyAbp.CacheManagement.CacheItems
{
public class CacheItemAppServiceTests : CacheManagementApplicationTestBase
{
private readonly ICacheItemAppService _cacheItemAppService;
public CacheItemAppServiceTests()
{
_cacheItemAppService = GetRequiredService<ICacheItemAppService>();
}
[Fact]
public async Task Test1()
{
// Arrange
// Act
// Assert
}
}
}
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace EasyAbp.CacheManagement.CacheItems
{
public class CacheItemDomainTests : CacheManagementDomainTestBase
{
public CacheItemDomainTests()
{
}
[Fact]
public async Task Test1()
{
// Arrange
// Assert
// Assert
}
}
}
using System;
using System.Threading.Tasks;
using EasyAbp.CacheManagement.CacheItems;
using Volo.Abp.Domain.Repositories;
using Xunit;
namespace EasyAbp.CacheManagement.EntityFrameworkCore.CacheItems
{
public class CacheItemRepositoryTests : CacheManagementEntityFrameworkCoreTestBase
{
private readonly IRepository<CacheItem, Guid> _cacheItemRepository;
public CacheItemRepositoryTests()
{
_cacheItemRepository = GetRequiredService<IRepository<CacheItem, Guid>>();
}
[Fact]
public async Task Test1()
{
await WithUnitOfWorkAsync(async () =>
{
// Arrange
// Act
//Assert
});
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment