feat(auth): extract Tenant to Platform domain
- Add Fengling.Platform domain and infrastructure projects - Move Tenant aggregate from AuthService/Console to Platform.Domain - Add TenantRepository and SeedData to Platform - Remove duplicate Tenant/TenantInfo models from AuthService and Console - Update controllers and services to use Platform.Domain.Tenant - Add new migrations for PlatformDbContext BREAKING CHANGE: Tenant entity now uses strongly-typed ID (TenantId)
This commit is contained in:
parent
9516e1cd93
commit
74122b2c8c
@ -1,5 +1,7 @@
|
|||||||
namespace Fengling.Console.Controllers;
|
namespace Fengling.Console.Controllers;
|
||||||
|
|
||||||
|
using Fengling.Console.Services;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 租户管理控制器
|
/// 租户管理控制器
|
||||||
/// 提供租户的增删改查以及租户用户、角色、配置管理功能
|
/// 提供租户的增删改查以及租户用户、角色、配置管理功能
|
||||||
@ -10,11 +12,13 @@ namespace Fengling.Console.Controllers;
|
|||||||
public class TenantsController : ControllerBase
|
public class TenantsController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ITenantService _tenantService;
|
private readonly ITenantService _tenantService;
|
||||||
|
private readonly IH5LinkService _h5LinkService;
|
||||||
private readonly ILogger<TenantsController> _logger;
|
private readonly ILogger<TenantsController> _logger;
|
||||||
|
|
||||||
public TenantsController(ITenantService tenantService, ILogger<TenantsController> logger)
|
public TenantsController(ITenantService tenantService, IH5LinkService h5LinkService, ILogger<TenantsController> logger)
|
||||||
{
|
{
|
||||||
_tenantService = tenantService;
|
_tenantService = tenantService;
|
||||||
|
_h5LinkService = h5LinkService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,4 +302,36 @@ public class TenantsController : ControllerBase
|
|||||||
return StatusCode(500, new { message = ex.Message });
|
return StatusCode(500, new { message = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成H5访问链接和二维码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">租户ID</param>
|
||||||
|
/// <returns>H5链接和二维码Base64</returns>
|
||||||
|
/// <response code="200">成功返回链接和二维码</response>
|
||||||
|
/// <response code="404">租户不存在</response>
|
||||||
|
/// <response code="500">服务器内部错误</response>
|
||||||
|
[HttpGet("{id}/h5-link")]
|
||||||
|
[Produces("application/json")]
|
||||||
|
[ProducesResponseType(typeof(H5LinkResult), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
||||||
|
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
||||||
|
public async Task<ActionResult<H5LinkResult>> GetH5Link(long id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _h5LinkService.GenerateH5LinkAsync(id);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Tenant not found: {TenantId}", id);
|
||||||
|
return NotFound(new { message = ex.Message });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error generating H5 link for tenant {TenantId}", id);
|
||||||
|
return StatusCode(500, new { message = "Failed to generate H5 link" });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -7,7 +7,6 @@ namespace Fengling.Console.Datas;
|
|||||||
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
|
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
|
||||||
: IdentityDbContext<ApplicationUser, ApplicationRole, long>(options)
|
: IdentityDbContext<ApplicationUser, ApplicationRole, long>(options)
|
||||||
{
|
{
|
||||||
public DbSet<Tenant> Tenants { get; set; }
|
|
||||||
public DbSet<AccessLog> AccessLogs { get; set; }
|
public DbSet<AccessLog> AccessLogs { get; set; }
|
||||||
public DbSet<AuditLog> AuditLogs { get; set; }
|
public DbSet<AuditLog> AuditLogs { get; set; }
|
||||||
|
|
||||||
@ -23,27 +22,16 @@ public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options
|
|||||||
|
|
||||||
entity.OwnsOne(e => e.TenantInfo, navigationBuilder =>
|
entity.OwnsOne(e => e.TenantInfo, navigationBuilder =>
|
||||||
{
|
{
|
||||||
navigationBuilder.Property(e => e.Id).HasColumnName("TenantId");
|
navigationBuilder.Property(e => e.TenantCode).HasColumnName("TenantCode");
|
||||||
navigationBuilder.Property(e => e.TenantId).HasColumnName("TenantCode");
|
navigationBuilder.Property(e => e.TenantId).HasColumnName("TenantId");
|
||||||
navigationBuilder.Property(e => e.Name).HasColumnName("TenantName");
|
navigationBuilder.Property(e => e.TenantName).HasColumnName("TenantName");
|
||||||
navigationBuilder.WithOwner();
|
navigationBuilder.WithOwner();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Entity<ApplicationRole>(entity => { entity.Property(e => e.Description).HasMaxLength(200); });
|
builder.Entity<ApplicationRole>(entity => { entity.Property(e => e.Description).HasMaxLength(200); });
|
||||||
|
|
||||||
builder.Entity<Tenant>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id);
|
|
||||||
entity.HasIndex(e => e.TenantId).IsUnique();
|
|
||||||
entity.Property(e => e.TenantId).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.Name).HasMaxLength(100);
|
|
||||||
entity.Property(e => e.ContactName).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.ContactEmail).HasMaxLength(100);
|
|
||||||
entity.Property(e => e.ContactPhone).HasMaxLength(20);
|
|
||||||
entity.Property(e => e.Status).HasMaxLength(20);
|
|
||||||
entity.Property(e => e.Description).HasMaxLength(500);
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Entity<AccessLog>(entity =>
|
builder.Entity<AccessLog>(entity =>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -25,11 +25,14 @@
|
|||||||
<PackageReference Include="OpenIddict.Server" />
|
<PackageReference Include="OpenIddict.Server" />
|
||||||
<PackageReference Include="OpenIddict.Server.AspNetCore" />
|
<PackageReference Include="OpenIddict.Server.AspNetCore" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" />
|
<PackageReference Include="Swashbuckle.AspNetCore" />
|
||||||
|
<PackageReference Include="SkiaSharp" />
|
||||||
|
<PackageReference Include="QRCoder" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- <ProjectReference Include="..\Fengling.AuthService\Fengling.AuthService.csproj" />-->
|
<!-- <ProjectReference Include="..\Fengling.AuthService\Fengling.AuthService.csproj" />-->
|
||||||
<ProjectReference Include="..\YarpGateway\YarpGateway.csproj" />
|
<ProjectReference Include="..\YarpGateway\YarpGateway.csproj" />
|
||||||
|
<ProjectReference Include="..\Fengling.Platform\Fengling.Platform.Infrastructure\Fengling.Platform.Infrastructure.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,63 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
public class Tenant
|
|
||||||
{
|
|
||||||
private long _id;
|
|
||||||
private string _tenantId;
|
|
||||||
private string _name;
|
|
||||||
|
|
||||||
[Key]
|
|
||||||
public long Id
|
|
||||||
{
|
|
||||||
get => _id;
|
|
||||||
set => _id = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
[Required]
|
|
||||||
public string TenantId
|
|
||||||
{
|
|
||||||
get => _tenantId;
|
|
||||||
set => _tenantId = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MaxLength(100)]
|
|
||||||
[Required]
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get => _name;
|
|
||||||
set => _name = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
[Required]
|
|
||||||
public string ContactName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(100)]
|
|
||||||
[Required]
|
|
||||||
[EmailAddress]
|
|
||||||
public string ContactEmail { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(20)]
|
|
||||||
public string? ContactPhone { get; set; }
|
|
||||||
|
|
||||||
public int? MaxUsers { get; set; }
|
|
||||||
|
|
||||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
||||||
|
|
||||||
[MaxLength(500)]
|
|
||||||
public string? Description { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(20)]
|
|
||||||
public string Status { get; set; } = "active";
|
|
||||||
|
|
||||||
public DateTime? ExpiresAt { get; set; }
|
|
||||||
|
|
||||||
public DateTime? UpdatedAt { get; set; }
|
|
||||||
|
|
||||||
public bool IsDeleted { get; set; }
|
|
||||||
|
|
||||||
public TenantInfo Info => new(Id, TenantId, Name);
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
namespace Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
public record TenantInfo(long Id, string TenantId, string Name);
|
|
||||||
@ -1,16 +1,17 @@
|
|||||||
using Fengling.Console.Models.Entities;
|
using Fengling.Console.Models.Entities;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
|
||||||
namespace Fengling.Console.Repositories;
|
namespace Fengling.Console.Repositories;
|
||||||
|
|
||||||
public interface ITenantRepository
|
public interface ITenantRepository
|
||||||
{
|
{
|
||||||
Task<Tenant?> GetByIdAsync(long id);
|
Task<Tenant?> GetByIdAsync(long id);
|
||||||
Task<Tenant?> GetByTenantIdAsync(string tenantId);
|
Task<Tenant?> GetByTenantCodeAsync(string tenantCode);
|
||||||
Task<IEnumerable<Tenant>> GetAllAsync();
|
Task<IEnumerable<Tenant>> GetAllAsync();
|
||||||
Task<IEnumerable<Tenant>> GetPagedAsync(int page, int pageSize, string? name = null, string? tenantId = null, string? status = null);
|
Task<IEnumerable<Tenant>> GetPagedAsync(int page, int pageSize, string? name = null, string? tenantCode = null, TenantStatus? status = null);
|
||||||
Task<int> CountAsync(string? name = null, string? tenantId = null, string? status = null);
|
Task<int> CountAsync(string? name = null, string? tenantCode = null, TenantStatus? status = null);
|
||||||
Task AddAsync(Tenant tenant);
|
Task AddAsync(Tenant tenant);
|
||||||
Task UpdateAsync(Tenant tenant);
|
Task UpdateAsync(Tenant tenant);
|
||||||
Task DeleteAsync(Tenant tenant);
|
Task DeleteAsync(Tenant tenant);
|
||||||
Task<int> GetUserCountAsync(long tenantId);
|
Task<int> GetUserCountAsync(TenantId tenantId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,21 @@
|
|||||||
using Fengling.Console.Datas;
|
using Fengling.Console.Datas;
|
||||||
using Fengling.Console.Models.Entities;
|
using Fengling.Console.Models.Entities;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Fengling.Console.Repositories;
|
namespace Fengling.Console.Repositories;
|
||||||
|
|
||||||
public class TenantRepository(ApplicationDbContext context) : ITenantRepository
|
public class TenantRepository(PlatformDbContext context,ApplicationDbContext identityDbContext) : ITenantRepository
|
||||||
{
|
{
|
||||||
public async Task<Tenant?> GetByIdAsync(long id)
|
public async Task<Tenant?> GetByIdAsync(long id)
|
||||||
{
|
{
|
||||||
return await context.Tenants.FindAsync(id);
|
return await context.Tenants.FindAsync(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Tenant?> GetByTenantIdAsync(string tenantId)
|
public async Task<Platform.Domain.AggregatesModel.TenantAggregate.Tenant?> GetByTenantCodeAsync(string tenantCode)
|
||||||
{
|
{
|
||||||
return await context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
|
return await context.Tenants.FirstOrDefaultAsync(t => t.TenantCode == tenantCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<Tenant>> GetAllAsync()
|
public async Task<IEnumerable<Tenant>> GetAllAsync()
|
||||||
@ -22,7 +24,7 @@ public class TenantRepository(ApplicationDbContext context) : ITenantRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<Tenant>> GetPagedAsync(int page, int pageSize, string? name = null,
|
public async Task<IEnumerable<Tenant>> GetPagedAsync(int page, int pageSize, string? name = null,
|
||||||
string? tenantId = null, string? status = null)
|
string? tenantCode = null, TenantStatus? status = null)
|
||||||
{
|
{
|
||||||
var query = context.Tenants.AsQueryable();
|
var query = context.Tenants.AsQueryable();
|
||||||
|
|
||||||
@ -31,12 +33,12 @@ public class TenantRepository(ApplicationDbContext context) : ITenantRepository
|
|||||||
query = query.Where(t => t.Name.Contains(name));
|
query = query.Where(t => t.Name.Contains(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
if (!string.IsNullOrEmpty(tenantCode))
|
||||||
{
|
{
|
||||||
query = query.Where(t => t.TenantId.Contains(tenantId));
|
query = query.Where(t => t.TenantCode.Contains(tenantCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(status))
|
if (status.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(t => t.Status == status);
|
query = query.Where(t => t.Status == status);
|
||||||
}
|
}
|
||||||
@ -48,7 +50,7 @@ public class TenantRepository(ApplicationDbContext context) : ITenantRepository
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> CountAsync(string? name = null, string? tenantId = null, string? status = null)
|
public async Task<int> CountAsync(string? name = null, string? tenantCode = null, TenantStatus? status = null)
|
||||||
{
|
{
|
||||||
var query = context.Tenants.AsQueryable();
|
var query = context.Tenants.AsQueryable();
|
||||||
|
|
||||||
@ -57,12 +59,12 @@ public class TenantRepository(ApplicationDbContext context) : ITenantRepository
|
|||||||
query = query.Where(t => t.Name.Contains(name));
|
query = query.Where(t => t.Name.Contains(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
if (!string.IsNullOrEmpty(tenantCode))
|
||||||
{
|
{
|
||||||
query = query.Where(t => t.TenantId.Contains(tenantId));
|
query = query.Where(t => t.TenantCode.Contains(tenantCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(status))
|
if (status.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(t => t.Status == status);
|
query = query.Where(t => t.Status == status);
|
||||||
}
|
}
|
||||||
@ -88,8 +90,8 @@ public class TenantRepository(ApplicationDbContext context) : ITenantRepository
|
|||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GetUserCountAsync(long tenantId)
|
public async Task<int> GetUserCountAsync(TenantId tenantId)
|
||||||
{
|
{
|
||||||
return await context.Users.CountAsync(u => u.TenantInfo.Id == tenantId && !u.IsDeleted);
|
return await identityDbContext.Users.CountAsync(u => u.TenantInfo.TenantId == tenantId && !u.IsDeleted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,7 +28,8 @@ public class UserRepository : IUserRepository
|
|||||||
return await _context.Users.ToListAsync();
|
return await _context.Users.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<ApplicationUser>> GetPagedAsync(int page, int pageSize, string? userName = null, string? email = null, string? tenantId = null)
|
public async Task<IEnumerable<ApplicationUser>> GetPagedAsync(int page, int pageSize, string? userName = null,
|
||||||
|
string? email = null, string? tenantCode = null)
|
||||||
{
|
{
|
||||||
var query = _context.Users.AsQueryable();
|
var query = _context.Users.AsQueryable();
|
||||||
|
|
||||||
@ -42,9 +43,9 @@ public class UserRepository : IUserRepository
|
|||||||
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
if (!string.IsNullOrEmpty(tenantCode))
|
||||||
{
|
{
|
||||||
query = query.Where(u => u.TenantInfo.Id.ToString() == tenantId);
|
query = query.Where(u => u.TenantInfo.TenantCode.Contains(tenantCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
return await query
|
return await query
|
||||||
@ -54,7 +55,7 @@ public class UserRepository : IUserRepository
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> CountAsync(string? userName = null, string? email = null, string? tenantId = null)
|
public async Task<int> CountAsync(string? userName = null, string? email = null, string? tenantCode = null)
|
||||||
{
|
{
|
||||||
var query = _context.Users.AsQueryable();
|
var query = _context.Users.AsQueryable();
|
||||||
|
|
||||||
@ -68,9 +69,9 @@ public class UserRepository : IUserRepository
|
|||||||
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
if (!string.IsNullOrEmpty(tenantCode))
|
||||||
{
|
{
|
||||||
query = query.Where(u => u.TenantInfo.Id.ToString() == tenantId);
|
query = query.Where(u => u.TenantInfo.TenantCode.Contains(tenantCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
return await query.CountAsync();
|
return await query.CountAsync();
|
||||||
|
|||||||
@ -4,12 +4,14 @@ using Microsoft.AspNetCore.Identity;
|
|||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Fengling.Console.Datas;
|
using Fengling.Console.Datas;
|
||||||
using Fengling.Console.Models.Entities;
|
using Fengling.Console.Models.Entities;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
|
||||||
namespace Fengling.Console.Services;
|
namespace Fengling.Console.Services;
|
||||||
|
|
||||||
public interface ITenantService
|
public interface ITenantService
|
||||||
{
|
{
|
||||||
Task<(IEnumerable<TenantDto> Items, int TotalCount)> GetTenantsAsync(int page, int pageSize, string? name = null, string? tenantId = null, string? status = null);
|
Task<(IEnumerable<TenantDto> Items, int TotalCount)> GetTenantsAsync(int page, int pageSize, string? name = null,
|
||||||
|
string? tenantCode = null, TenantStatus? status = null);
|
||||||
Task<TenantDto?> GetTenantAsync(long id);
|
Task<TenantDto?> GetTenantAsync(long id);
|
||||||
Task<IEnumerable<UserDto>> GetTenantUsersAsync(long tenantId);
|
Task<IEnumerable<UserDto>> GetTenantUsersAsync(long tenantId);
|
||||||
Task<IEnumerable<object>> GetTenantRolesAsync(long tenantId);
|
Task<IEnumerable<object>> GetTenantRolesAsync(long tenantId);
|
||||||
@ -29,10 +31,11 @@ public class TenantService(
|
|||||||
IHttpContextAccessor httpContextAccessor)
|
IHttpContextAccessor httpContextAccessor)
|
||||||
: ITenantService
|
: ITenantService
|
||||||
{
|
{
|
||||||
public async Task<(IEnumerable<TenantDto> Items, int TotalCount)> GetTenantsAsync(int page, int pageSize, string? name = null, string? tenantId = null, string? status = null)
|
public async Task<(IEnumerable<TenantDto> Items, int TotalCount)> GetTenantsAsync
|
||||||
|
(int page, int pageSize, string? name = null, string? tenantCode = null, TenantStatus? status = null)
|
||||||
{
|
{
|
||||||
var tenants = await repository.GetPagedAsync(page, pageSize, name, tenantId, status);
|
var tenants = await repository.GetPagedAsync(page, pageSize, name, tenantCode, status);
|
||||||
var totalCount = await repository.CountAsync(name, tenantId, status);
|
var totalCount = await repository.CountAsync(name, tenantCode, status);
|
||||||
|
|
||||||
var tenantDtos = new List<TenantDto>();
|
var tenantDtos = new List<TenantDto>();
|
||||||
foreach (var tenant in tenants)
|
foreach (var tenant in tenants)
|
||||||
@ -41,7 +44,7 @@ public class TenantService(
|
|||||||
tenantDtos.Add(new TenantDto
|
tenantDtos.Add(new TenantDto
|
||||||
{
|
{
|
||||||
Id = tenant.Id,
|
Id = tenant.Id,
|
||||||
TenantId = tenant.TenantId,
|
TenantCode = tenant.TenantCode,
|
||||||
Name = tenant.Name,
|
Name = tenant.Name,
|
||||||
ContactName = tenant.ContactName,
|
ContactName = tenant.ContactName,
|
||||||
ContactEmail = tenant.ContactEmail,
|
ContactEmail = tenant.ContactEmail,
|
||||||
@ -66,7 +69,7 @@ public class TenantService(
|
|||||||
return new TenantDto
|
return new TenantDto
|
||||||
{
|
{
|
||||||
Id = tenant.Id,
|
Id = tenant.Id,
|
||||||
TenantId = tenant.TenantId,
|
TenantCode = tenant.TenantCode,
|
||||||
Name = tenant.Name,
|
Name = tenant.Name,
|
||||||
ContactName = tenant.ContactName,
|
ContactName = tenant.ContactName,
|
||||||
ContactEmail = tenant.ContactEmail,
|
ContactEmail = tenant.ContactEmail,
|
||||||
@ -100,8 +103,8 @@ public class TenantService(
|
|||||||
UserName = user.UserName,
|
UserName = user.UserName,
|
||||||
Email = user.Email,
|
Email = user.Email,
|
||||||
RealName = user.RealName,
|
RealName = user.RealName,
|
||||||
TenantId = user.TenantInfo.Id,
|
TenantCode = user.TenantInfo.TenantCode,
|
||||||
TenantName = user.TenantInfo.Name,
|
TenantName = user.TenantInfo.TenantName,
|
||||||
Roles = roles.ToList(),
|
Roles = roles.ToList(),
|
||||||
EmailConfirmed = user.EmailConfirmed,
|
EmailConfirmed = user.EmailConfirmed,
|
||||||
IsActive = !user.LockoutEnabled || user.LockoutEnd == null || user.LockoutEnd < DateTimeOffset.UtcNow,
|
IsActive = !user.LockoutEnabled || user.LockoutEnd == null || user.LockoutEnd < DateTimeOffset.UtcNow,
|
||||||
@ -156,33 +159,23 @@ public class TenantService(
|
|||||||
throw new KeyNotFoundException($"Tenant with ID {id} not found");
|
throw new KeyNotFoundException($"Tenant with ID {id} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "update", "TenantSettings", tenant.Id, tenant.TenantId, null, System.Text.Json.JsonSerializer.Serialize(settings));
|
await CreateAuditLog("tenant", "update", "TenantSettings", tenant.Id, tenant.Name, null, System.Text.Json.JsonSerializer.Serialize(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TenantDto> CreateTenantAsync(CreateTenantDto dto)
|
public async Task<TenantDto> CreateTenantAsync(CreateTenantDto dto)
|
||||||
{
|
{
|
||||||
var tenant = new Tenant
|
var tenant = new Tenant(dto.TenantCode, dto.Name, dto.ContactName, dto.ContactEmail,
|
||||||
{
|
dto.ContactPhone,dto.MaxUsers,dto.Description,dto.ExpiresAt);
|
||||||
TenantId = dto.TenantId,
|
|
||||||
Name = dto.Name,
|
|
||||||
ContactName = dto.ContactName,
|
|
||||||
ContactEmail = dto.ContactEmail,
|
|
||||||
ContactPhone = dto.ContactPhone,
|
|
||||||
MaxUsers = dto.MaxUsers,
|
|
||||||
Description = dto.Description,
|
|
||||||
Status = dto.Status,
|
|
||||||
ExpiresAt = dto.ExpiresAt,
|
|
||||||
CreatedAt = DateTime.UtcNow
|
|
||||||
};
|
|
||||||
|
|
||||||
await repository.AddAsync(tenant);
|
await repository.AddAsync(tenant);
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "create", "Tenant", tenant.Id, tenant.TenantId, null, System.Text.Json.JsonSerializer.Serialize(dto));
|
await CreateAuditLog("tenant", "create", "Tenant", tenant.Id, tenant.Name, null,
|
||||||
|
System.Text.Json.JsonSerializer.Serialize(dto));
|
||||||
|
|
||||||
return new TenantDto
|
return new TenantDto
|
||||||
{
|
{
|
||||||
Id = tenant.Id,
|
Id = tenant.Id,
|
||||||
TenantId = tenant.TenantId,
|
TenantCode = tenant.TenantCode,
|
||||||
Name = tenant.Name,
|
Name = tenant.Name,
|
||||||
ContactName = tenant.ContactName,
|
ContactName = tenant.ContactName,
|
||||||
ContactEmail = tenant.ContactEmail,
|
ContactEmail = tenant.ContactEmail,
|
||||||
@ -206,24 +199,17 @@ public class TenantService(
|
|||||||
|
|
||||||
var oldValue = System.Text.Json.JsonSerializer.Serialize(tenant);
|
var oldValue = System.Text.Json.JsonSerializer.Serialize(tenant);
|
||||||
|
|
||||||
tenant.Name = dto.Name;
|
tenant.UpdateInfo(dto.Name,dto.ContactName,dto.ContactEmail,dto.ContactPhone);
|
||||||
tenant.ContactName = dto.ContactName;
|
|
||||||
tenant.ContactEmail = dto.ContactEmail;
|
|
||||||
tenant.ContactPhone = dto.ContactPhone;
|
|
||||||
tenant.MaxUsers = dto.MaxUsers;
|
|
||||||
tenant.Description = dto.Description;
|
|
||||||
tenant.Status = dto.Status;
|
|
||||||
tenant.ExpiresAt = dto.ExpiresAt;
|
|
||||||
tenant.UpdatedAt = DateTime.UtcNow;
|
|
||||||
|
|
||||||
await repository.UpdateAsync(tenant);
|
await repository.UpdateAsync(tenant);
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "update", "Tenant", tenant.Id, tenant.TenantId, oldValue, System.Text.Json.JsonSerializer.Serialize(tenant));
|
await CreateAuditLog("tenant", "update", "Tenant", tenant.Id, tenant.Name, oldValue,
|
||||||
|
System.Text.Json.JsonSerializer.Serialize(tenant));
|
||||||
|
|
||||||
return new TenantDto
|
return new TenantDto
|
||||||
{
|
{
|
||||||
Id = tenant.Id,
|
Id = tenant.Id,
|
||||||
TenantId = tenant.TenantId,
|
TenantCode = tenant.TenantCode,
|
||||||
Name = tenant.Name,
|
Name = tenant.Name,
|
||||||
ContactName = tenant.ContactName,
|
ContactName = tenant.ContactName,
|
||||||
ContactEmail = tenant.ContactEmail,
|
ContactEmail = tenant.ContactEmail,
|
||||||
@ -255,10 +241,10 @@ public class TenantService(
|
|||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
tenant.IsDeleted = true;
|
tenant.Delete();;
|
||||||
await repository.UpdateAsync(tenant);
|
await repository.UpdateAsync(tenant);
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "delete", "Tenant", tenant.Id, tenant.TenantId, oldValue);
|
await CreateAuditLog("tenant", "delete", "Tenant", tenant.Id, tenant.Name, oldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CreateAuditLog(string operation, string action, string targetType, long? targetId, string? targetName, string? oldValue = null, string? newValue = null)
|
private async Task CreateAuditLog(string operation, string action, string targetType, long? targetId, string? targetName, string? oldValue = null, string? newValue = null)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user