Browse Source

feat(saas): add validation before version changes

pull/518/head
cKey 4 years ago
parent
commit
a2905dae7d
  1. 15
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN/Abp/Saas/Editions/EditionAppService.cs
  2. 30
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN/Abp/Saas/Tenants/TenantAppService.cs
  3. 1
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/AbpSaasErrorCodes.cs
  4. 1
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/en.json
  5. 1
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/zh-Hans.json
  6. 11
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Editions/EditionManager.cs
  7. 4
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Editions/IEditionRepository.cs
  8. 7
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Tenants/TenantCacheItemInvalidator.cs
  9. 11
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.EntityFrameworkCore/LINGYUN/Abp/Saas/EntityFrameworkCore/EfCoreEditionRepository.cs

15
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN/Abp/Saas/Editions/EditionAppService.cs

@ -37,12 +37,9 @@ public class EditionAppService : AbpSaasAppServiceBase, IEditionAppService
[Authorize(AbpSaasPermissions.Editions.Delete)]
public async virtual Task DeleteAsync(Guid id)
{
var edition = await EditionRepository.FindAsync(id);
if (edition == null)
{
return;
}
await EditionRepository.DeleteAsync(edition);
var edition = await EditionRepository.GetAsync(id);
await EditionManager.DeleteAsync(edition);
}
public async virtual Task<EditionDto> GetAsync(Guid id)
@ -73,7 +70,11 @@ public class EditionAppService : AbpSaasAppServiceBase, IEditionAppService
{
var edition = await EditionRepository.GetAsync(id, false);
await EditionManager.ChangeDisplayNameAsync(edition, input.DisplayName);
if (!string.Equals(edition.DisplayName, input.DisplayName))
{
await EditionManager.ChangeDisplayNameAsync(edition, input.DisplayName);
}
input.MapExtraPropertiesTo(edition);
await EditionRepository.UpdateAsync(edition);

30
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Application/LINGYUN/Abp/Saas/Tenants/TenantAppService.cs

@ -1,5 +1,4 @@
using LINGYUN.Abp.MultiTenancy;
using LINGYUN.Abp.Saas.Editions;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
@ -16,19 +15,16 @@ namespace LINGYUN.Abp.Saas.Tenants;
public class TenantAppService : AbpSaasAppServiceBase, ITenantAppService
{
protected IDistributedEventBus EventBus { get; }
protected IEditionRepository EditionRepository { get; }
protected ITenantRepository TenantRepository { get; }
protected ITenantManager TenantManager { get; }
public TenantAppService(
ITenantRepository tenantRepository,
IEditionRepository editionRepository,
ITenantManager tenantManager,
IDistributedEventBus eventBus)
{
EventBus = eventBus;
TenantRepository = tenantRepository;
EditionRepository = editionRepository;
TenantManager = tenantManager;
}
@ -40,15 +36,7 @@ public class TenantAppService : AbpSaasAppServiceBase, ITenantAppService
throw new UserFriendlyException(L["TenantNotFoundById", id]);
}
var tenantDto = ObjectMapper.Map<Tenant, TenantDto>(tenant);
if (tenant.EditionId.HasValue)
{
var edition = await EditionRepository.GetAsync(tenant.EditionId.Value);
tenantDto.EditionId = edition.Id;
tenantDto.EditionName = edition.DisplayName;
}
return tenantDto;
return ObjectMapper.Map<Tenant, TenantDto>(tenant);
}
public virtual async Task<TenantDto> GetAsync(string name)
@ -58,15 +46,7 @@ public class TenantAppService : AbpSaasAppServiceBase, ITenantAppService
{
throw new UserFriendlyException(L["TenantNotFoundByName", name]);
}
var tenantDto = ObjectMapper.Map<Tenant, TenantDto>(tenant);
if (tenant.EditionId.HasValue)
{
var edition = await EditionRepository.GetAsync(tenant.EditionId.Value);
tenantDto.EditionId = edition.Id;
tenantDto.EditionName = edition.DisplayName;
}
return tenantDto;
return ObjectMapper.Map<Tenant, TenantDto>(tenant);
}
public virtual async Task<PagedResultDto<TenantDto>> GetListAsync(TenantGetListInput input)
@ -123,7 +103,11 @@ public class TenantAppService : AbpSaasAppServiceBase, ITenantAppService
{
var tenant = await TenantRepository.GetAsync(id, false);
await TenantManager.ChangeNameAsync(tenant, input.Name);
if (!string.Equals(tenant.Name, input.Name))
{
await TenantManager.ChangeNameAsync(tenant, input.Name);
}
tenant.IsActive = input.IsActive;
tenant.EditionId = input.EditionId;
input.MapExtraPropertiesTo(tenant);

1
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/AbpSaasErrorCodes.cs

@ -5,5 +5,6 @@ public static class AbpSaasErrorCodes
public const string Namespace = "Saas";
public const string DuplicateEditionDisplayName = Namespace + ":010001";
public const string DeleteUsedEdition = Namespace + ":010002";
public const string DuplicateTenantName = Namespace + ":020001";
}

1
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/en.json

@ -2,6 +2,7 @@
"culture": "en",
"texts": {
"Saas:010001": "Unable to create duplicate editions {DisplayName}!",
"Saas:010002": "Tried to delete the edition in use: {DisplayName}!",
"Saas:020001": "Unable to create duplicate tenants {Name}!",
"Volo.AbpIo.MultiTenancy:010001": "The tenant is unavailable or restricted!",
"Volo.AbpIo.MultiTenancy:010002": "Tenant unavailable!",

1
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain.Shared/LINGYUN/Abp/Saas/Localization/Resources/zh-Hans.json

@ -2,6 +2,7 @@
"culture": "zh-Hans",
"texts": {
"Saas:010001": "已经存在名为 {DisplayName} 的版本!",
"Saas:010002": "试图删除正在使用的版本: {DisplayName}!",
"Saas:020001": "已经存在名为 {Name} 的租户!",
"Volo.AbpIo.MultiTenancy:010001": "租户不可用或受限制!",
"Volo.AbpIo.MultiTenancy:010002": "租户不可用!",

11
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Editions/EditionManager.cs

@ -12,10 +12,19 @@ public class EditionManager : DomainService
public EditionManager(IEditionRepository editionRepository)
{
EditionRepository = editionRepository;
}
public async virtual Task DeleteAsync(Edition edition)
{
if (await EditionRepository.CheckUsedByTenantAsync(edition.Id))
{
throw new BusinessException(AbpSaasErrorCodes.DeleteUsedEdition)
.WithData(nameof(Edition.DisplayName), edition.DisplayName);
}
await EditionRepository.DeleteAsync(edition);
}
public virtual async Task<Edition> CreateAsync(string displayName)
public async virtual Task<Edition> CreateAsync(string displayName)
{
Check.NotNull(displayName, nameof(displayName));

4
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Editions/IEditionRepository.cs

@ -8,6 +8,10 @@ namespace LINGYUN.Abp.Saas.Editions;
public interface IEditionRepository : IBasicRepository<Edition, Guid>
{
Task<bool> CheckUsedByTenantAsync(
Guid id,
CancellationToken cancellationToken = default);
Task<Edition> FindByDisplayNameAsync(
string displayName,
CancellationToken cancellationToken = default);

7
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/Tenants/TenantCacheItemInvalidator.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using LINGYUN.Abp.Saas.Editions;
using System.Threading.Tasks;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
@ -17,6 +18,8 @@ public class TenantCacheItemInvalidator : ILocalEventHandler<EntityChangedEventD
public virtual async Task HandleEventAsync(EntityChangedEventData<Tenant> eventData)
{
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(eventData.Entity.Id, eventData.Entity.Name), considerUow: true);
await Cache.RemoveAsync(TenantCacheItem.CalculateCacheKey(eventData.Entity.Id, eventData.Entity.Name), considerUow: true);
// 同时移除租户版本缓存
await Cache.RemoveAsync(EditionCacheItem.CalculateCacheKey(eventData.Entity.Id), considerUow: true);
}
}

11
aspnet-core/modules/saas/LINGYUN.Abp.Saas.EntityFrameworkCore/LINGYUN/Abp/Saas/EntityFrameworkCore/EfCoreEditionRepository.cs

@ -20,6 +20,17 @@ public class EfCoreEditionRepository : EfCoreRepository<ISaasDbContext, Edition,
{
}
public async virtual Task<bool> CheckUsedByTenantAsync(
Guid id,
CancellationToken cancellationToken = default)
{
var dbContext = await GetDbContextAsync();
var tenantDbSet = dbContext.Set<Tenant>();
return await tenantDbSet
.AnyAsync(x => x.EditionId == id, GetCancellationToken(cancellationToken));
}
public async virtual Task<Edition> FindByDisplayNameAsync(
string displayName,
CancellationToken cancellationToken = default)

Loading…
Cancel
Save