Compare commits
10 Commits
f14bf019f1
...
df7c7e0717
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df7c7e0717 | ||
|
|
fc8fcc7de2 | ||
|
|
f33acacbbc | ||
|
|
d32b44bfc4 | ||
|
|
0d64b61169 | ||
|
|
28de202556 | ||
|
|
f5d6e0652c | ||
|
|
4d2127637d | ||
|
|
74122b2c8c | ||
| 9516e1cd93 |
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +68,7 @@ public class TenantsController : ControllerBase
|
|||||||
[ProducesResponseType(typeof(TenantDto), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(TenantDto), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<ActionResult<TenantDto>> GetTenant(long id)
|
public async Task<ActionResult<TenantDto>> GetTenant(int id)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -96,7 +100,7 @@ public class TenantsController : ControllerBase
|
|||||||
[ProducesResponseType(typeof(IEnumerable<UserDto>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(IEnumerable<UserDto>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<ActionResult<IEnumerable<UserDto>>> GetTenantUsers(long tenantId)
|
public async Task<ActionResult<IEnumerable<UserDto>>> GetTenantUsers(int tenantId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -128,7 +132,7 @@ public class TenantsController : ControllerBase
|
|||||||
[ProducesResponseType(typeof(IEnumerable<object>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(IEnumerable<object>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<ActionResult<IEnumerable<object>>> GetTenantRoles(long tenantId)
|
public async Task<ActionResult<IEnumerable<object>>> GetTenantRoles(int tenantId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -160,7 +164,7 @@ public class TenantsController : ControllerBase
|
|||||||
[ProducesResponseType(typeof(TenantSettingsDto), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(TenantSettingsDto), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<ActionResult<TenantSettingsDto>> GetTenantSettings(long id)
|
public async Task<ActionResult<TenantSettingsDto>> GetTenantSettings(int id)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -192,7 +196,7 @@ public class TenantsController : ControllerBase
|
|||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<IActionResult> UpdateTenantSettings(long id, [FromBody] TenantSettingsDto settings)
|
public async Task<IActionResult> UpdateTenantSettings(int id, [FromBody] TenantSettingsDto settings)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -249,7 +253,7 @@ public class TenantsController : ControllerBase
|
|||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<IActionResult> UpdateTenant(long id, [FromBody] UpdateTenantDto dto)
|
public async Task<IActionResult> UpdateTenant(int id, [FromBody] UpdateTenantDto dto)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -280,7 +284,7 @@ public class TenantsController : ControllerBase
|
|||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
[ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<IActionResult> DeleteTenant(long id)
|
public async Task<IActionResult> DeleteTenant(int id)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -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(int 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" });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,85 +0,0 @@
|
|||||||
using Fengling.Console.Models.Entities;
|
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Datas;
|
|
||||||
|
|
||||||
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
|
|
||||||
: IdentityDbContext<ApplicationUser, ApplicationRole, long>(options)
|
|
||||||
{
|
|
||||||
public DbSet<Tenant> Tenants { get; set; }
|
|
||||||
public DbSet<AccessLog> AccessLogs { get; set; }
|
|
||||||
public DbSet<AuditLog> AuditLogs { get; set; }
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder builder)
|
|
||||||
{
|
|
||||||
base.OnModelCreating(builder);
|
|
||||||
|
|
||||||
builder.Entity<ApplicationUser>(entity =>
|
|
||||||
{
|
|
||||||
entity.Property(e => e.RealName).HasMaxLength(100);
|
|
||||||
entity.Property(e => e.Phone).HasMaxLength(20);
|
|
||||||
entity.HasIndex(e => e.Phone).IsUnique();
|
|
||||||
|
|
||||||
entity.OwnsOne(e => e.TenantInfo, navigationBuilder =>
|
|
||||||
{
|
|
||||||
navigationBuilder.Property(e => e.Id).HasColumnName("TenantId");
|
|
||||||
navigationBuilder.Property(e => e.TenantId).HasColumnName("TenantCode");
|
|
||||||
navigationBuilder.Property(e => e.Name).HasColumnName("TenantName");
|
|
||||||
navigationBuilder.WithOwner();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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 =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id);
|
|
||||||
entity.HasIndex(e => e.CreatedAt);
|
|
||||||
entity.HasIndex(e => e.UserName);
|
|
||||||
entity.HasIndex(e => e.TenantId);
|
|
||||||
entity.HasIndex(e => e.Action);
|
|
||||||
entity.HasIndex(e => e.Status);
|
|
||||||
entity.Property(e => e.UserName).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.TenantId).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.Action).HasMaxLength(20);
|
|
||||||
entity.Property(e => e.Resource).HasMaxLength(200);
|
|
||||||
entity.Property(e => e.Method).HasMaxLength(10);
|
|
||||||
entity.Property(e => e.IpAddress).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.UserAgent).HasMaxLength(500);
|
|
||||||
entity.Property(e => e.Status).HasMaxLength(20);
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Entity<AuditLog>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id);
|
|
||||||
entity.HasIndex(e => e.CreatedAt);
|
|
||||||
entity.HasIndex(e => e.Operator);
|
|
||||||
entity.HasIndex(e => e.TenantId);
|
|
||||||
entity.HasIndex(e => e.Operation);
|
|
||||||
entity.HasIndex(e => e.Action);
|
|
||||||
entity.Property(e => e.Operator).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.TenantId).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.Operation).HasMaxLength(20);
|
|
||||||
entity.Property(e => e.Action).HasMaxLength(20);
|
|
||||||
entity.Property(e => e.TargetType).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.TargetName).HasMaxLength(100);
|
|
||||||
entity.Property(e => e.IpAddress).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.Description).HasMaxLength(500);
|
|
||||||
entity.Property(e => e.Status).HasMaxLength(20);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,6 +4,7 @@
|
|||||||
<TargetFramework>net10.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
@ -18,6 +19,8 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
|
||||||
|
<PackageReference Include="NetCorePal.Extensions.AspNetCore" />
|
||||||
|
<PackageReference Include="NetCorePal.Extensions.DistributedLocks.Redis" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
|
||||||
<PackageReference Include="OpenIddict.Abstractions" />
|
<PackageReference Include="OpenIddict.Abstractions" />
|
||||||
<PackageReference Include="OpenIddict.AspNetCore" />
|
<PackageReference Include="OpenIddict.AspNetCore" />
|
||||||
@ -25,11 +28,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>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace Fengling.Console.Models.Dtos;
|
|||||||
public class CreateTenantDto
|
public class CreateTenantDto
|
||||||
{
|
{
|
||||||
[Required]
|
[Required]
|
||||||
public string TenantId { get; set; } = string.Empty;
|
public string TenantCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
@ -26,4 +26,16 @@ public class CreateTenantDto
|
|||||||
public string Status { get; set; } = "active";
|
public string Status { get; set; } = "active";
|
||||||
|
|
||||||
public DateTime? ExpiresAt { get; set; }
|
public DateTime? ExpiresAt { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(255)]
|
||||||
|
public string? CustomDomain { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(50)]
|
||||||
|
public string? BasePath { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(500)]
|
||||||
|
public string? Logo { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(500)]
|
||||||
|
public string? H5BaseUrl { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ public class CreateUserDto
|
|||||||
[Required]
|
[Required]
|
||||||
public string RealName { get; set; } = string.Empty;
|
public string RealName { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string? Phone { get; set; }
|
public string? PhoneNumber { get; set; }
|
||||||
|
|
||||||
public long? TenantId { get; set; }
|
public long? TenantId { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -10,5 +10,5 @@ public class RoleDto
|
|||||||
public bool IsSystem { get; set; }
|
public bool IsSystem { get; set; }
|
||||||
public List<string>? Permissions { get; set; }
|
public List<string>? Permissions { get; set; }
|
||||||
public int UserCount { get; set; }
|
public int UserCount { get; set; }
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTimeOffset CreatedAt { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,23 @@
|
|||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
|
||||||
namespace Fengling.Console.Models.Dtos;
|
namespace Fengling.Console.Models.Dtos;
|
||||||
|
|
||||||
public class TenantDto
|
public class TenantDto
|
||||||
{
|
{
|
||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
public string TenantId { get; set; } = "";
|
public string TenantCode { get; set; } = "";
|
||||||
public string Name { get; set; } = "";
|
public string Name { get; set; } = "";
|
||||||
public string ContactName { get; set; } = "";
|
public string ContactName { get; set; } = "";
|
||||||
public string ContactEmail { get; set; } = "";
|
public string ContactEmail { get; set; } = "";
|
||||||
public string? ContactPhone { get; set; }
|
public string? ContactPhone { get; set; }
|
||||||
public int? MaxUsers { get; set; }
|
public int? MaxUsers { get; set; }
|
||||||
public int UserCount { get; set; }
|
public int UserCount { get; set; }
|
||||||
public string Status { get; set; } = "active";
|
public TenantStatus Status { get; set; } = TenantStatus.Active;
|
||||||
public DateTime? ExpiresAt { get; set; }
|
public DateTime? ExpiresAt { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public string? CustomDomain { get; set; }
|
||||||
|
public string? BasePath { get; set; }
|
||||||
|
public string? Logo { get; set; }
|
||||||
|
public string? H5BaseUrl { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
|
||||||
namespace Fengling.Console.Models.Dtos;
|
namespace Fengling.Console.Models.Dtos;
|
||||||
|
|
||||||
public class TenantQueryDto : PaginationQueryDto
|
public class TenantQueryDto : PaginationQueryDto
|
||||||
@ -6,5 +8,5 @@ public class TenantQueryDto : PaginationQueryDto
|
|||||||
|
|
||||||
public string? TenantId { get; set; }
|
public string? TenantId { get; set; }
|
||||||
|
|
||||||
public string? Status { get; set; }
|
public TenantStatus? Status { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,4 +23,16 @@ public class UpdateTenantDto
|
|||||||
public string Status { get; set; } = "active";
|
public string Status { get; set; } = "active";
|
||||||
|
|
||||||
public DateTime? ExpiresAt { get; set; }
|
public DateTime? ExpiresAt { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(255)]
|
||||||
|
public string? CustomDomain { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(50)]
|
||||||
|
public string? BasePath { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(500)]
|
||||||
|
public string? Logo { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(500)]
|
||||||
|
public string? H5BaseUrl { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ public class UpdateUserDto
|
|||||||
[Required]
|
[Required]
|
||||||
public string RealName { get; set; } = string.Empty;
|
public string RealName { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string? Phone { get; set; }
|
public string? PhoneNumber { get; set; }
|
||||||
|
|
||||||
public bool EmailConfirmed { get; set; }
|
public bool EmailConfirmed { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -6,11 +6,11 @@ public class UserDto
|
|||||||
public string? UserName { get; set; }
|
public string? UserName { get; set; }
|
||||||
public string? Email { get; set; }
|
public string? Email { get; set; }
|
||||||
public string? RealName { get; set; }
|
public string? RealName { get; set; }
|
||||||
public string? Phone { get; set; }
|
public string? PhoneNumber { get; set; }
|
||||||
public long TenantId { get; set; }
|
public string? TenantCode { get; set; } = "";
|
||||||
public string TenantName { get; set; } = "";
|
public string? TenantName { get; set; } = "";
|
||||||
public List<string> Roles { get; set; } = new();
|
public List<string> Roles { get; set; } = new();
|
||||||
public bool EmailConfirmed { get; set; }
|
public bool EmailConfirmed { get; set; }
|
||||||
public bool IsActive { get; set; }
|
public bool IsActive { get; set; }
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTimeOffset CreatedAt { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,43 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
public class AccessLog
|
|
||||||
{
|
|
||||||
[Key]
|
|
||||||
public long Id { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
public string? UserName { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
public string? TenantId { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(20)]
|
|
||||||
public string Action { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(200)]
|
|
||||||
public string? Resource { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(10)]
|
|
||||||
public string? Method { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
public string? IpAddress { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(500)]
|
|
||||||
public string? UserAgent { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(20)]
|
|
||||||
public string Status { get; set; } = "success";
|
|
||||||
|
|
||||||
public int Duration { get; set; }
|
|
||||||
|
|
||||||
public string? RequestData { get; set; }
|
|
||||||
|
|
||||||
public string? ResponseData { get; set; }
|
|
||||||
|
|
||||||
public string? ErrorMessage { get; set; }
|
|
||||||
|
|
||||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
public class ApplicationRole : IdentityRole<long>
|
|
||||||
{
|
|
||||||
public string? Description { get; set; }
|
|
||||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
|
||||||
public long? TenantId { get; set; }
|
|
||||||
public bool IsSystem { get; set; }
|
|
||||||
public string? DisplayName { get; set; }
|
|
||||||
public List<string>? Permissions { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
public class ApplicationUser : IdentityUser<long>
|
|
||||||
{
|
|
||||||
public string? RealName { get; set; }
|
|
||||||
public string? Phone { get; set; }
|
|
||||||
public TenantInfo TenantInfo { get; set; } = null!;
|
|
||||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
|
||||||
public DateTime? UpdatedTime { get; set; }
|
|
||||||
public bool IsDeleted { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
public class AuditLog
|
|
||||||
{
|
|
||||||
[Key]
|
|
||||||
public long Id { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
[Required]
|
|
||||||
public string Operator { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
public string? TenantId { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(20)]
|
|
||||||
public string Operation { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(20)]
|
|
||||||
public string Action { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
public string? TargetType { get; set; }
|
|
||||||
|
|
||||||
public long? TargetId { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(100)]
|
|
||||||
public string? TargetName { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(50)]
|
|
||||||
public string IpAddress { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(500)]
|
|
||||||
public string? Description { get; set; }
|
|
||||||
|
|
||||||
public string? OldValue { get; set; }
|
|
||||||
|
|
||||||
public string? NewValue { get; set; }
|
|
||||||
|
|
||||||
public string? ErrorMessage { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(20)]
|
|
||||||
public string Status { get; set; } = "success";
|
|
||||||
|
|
||||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
46
Program.cs
46
Program.cs
@ -1,14 +1,15 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Fengling.Console.Repositories;
|
|
||||||
using Fengling.Console.Services;
|
using Fengling.Console.Services;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.UserAggregate;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.RoleAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
using OpenIddict.Abstractions;
|
using OpenIddict.Abstractions;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Fengling.Console.Datas;
|
using NetCorePal.Extensions.DependencyInjection;
|
||||||
using Fengling.Console.Models.Entities;
|
|
||||||
using OpenIddict.Validation.AspNetCore;
|
using OpenIddict.Validation.AspNetCore;
|
||||||
using YarpGateway.Data;
|
using YarpGateway.Data;
|
||||||
|
|
||||||
@ -16,35 +17,42 @@ var builder = WebApplication.CreateBuilder(args);
|
|||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
builder.Services.AddDbContext<ApplicationDbContext>(options =>
|
// Use PlatformDbContext for all identity
|
||||||
|
builder.Services.AddDbContext<PlatformDbContext>(options =>
|
||||||
{
|
{
|
||||||
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"));
|
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"));
|
||||||
|
if (builder.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
options.EnableSensitiveDataLogging();
|
||||||
|
}
|
||||||
|
options.EnableDetailedErrors();
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Services.AddDbContext<GatewayDbContext>(options =>
|
builder.Services.AddDbContext<GatewayDbContext>(options =>
|
||||||
options.UseNpgsql(builder.Configuration.GetConnectionString("GatewayConnection")));
|
options.UseNpgsql(builder.Configuration.GetConnectionString("GatewayConnection")));
|
||||||
|
|
||||||
|
// Use Platform's identity
|
||||||
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>()
|
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>()
|
||||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
.AddEntityFrameworkStores<PlatformDbContext>()
|
||||||
.AddDefaultTokenProviders();
|
.AddDefaultTokenProviders();
|
||||||
|
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
|
|
||||||
builder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
builder.Services.AddScoped<IOAuthClientService, OAuthClientService>();
|
builder.Services.AddScoped<IOAuthClientService, OAuthClientService>();
|
||||||
builder.Services.AddScoped<IUserRepository, UserRepository>();
|
|
||||||
builder.Services.AddScoped<ITenantRepository, TenantRepository>();
|
// Register Platform managers
|
||||||
builder.Services.AddScoped<IRoleRepository, RoleRepository>();
|
builder.Services.AddScoped<ITenantStore, TenantStore>();
|
||||||
|
builder.Services.AddScoped<ITenantManager, TenantManager>();
|
||||||
|
|
||||||
builder.Services.AddScoped<IUserService, UserService>();
|
builder.Services.AddScoped<IUserService, UserService>();
|
||||||
builder.Services.AddScoped<ITenantService, TenantService>();
|
builder.Services.AddScoped<ITenantService, TenantService>();
|
||||||
builder.Services.AddScoped<IRoleService, RoleService>();
|
builder.Services.AddScoped<IRoleService, RoleService>();
|
||||||
|
builder.Services.AddScoped<IGatewayService, GatewayService>();
|
||||||
|
builder.Services.AddScoped<IH5LinkService, H5LinkService>();
|
||||||
|
|
||||||
builder.Services.AddOpenIddict()
|
builder.Services.AddOpenIddict()
|
||||||
.AddCore(options =>
|
.AddCore(options => { options.UseEntityFrameworkCore().UseDbContext<PlatformDbContext>(); })
|
||||||
{
|
|
||||||
options.UseEntityFrameworkCore().UseDbContext<ApplicationDbContext>();
|
|
||||||
})
|
|
||||||
.AddValidation(options =>
|
.AddValidation(options =>
|
||||||
{
|
{
|
||||||
options.SetIssuer("http://localhost:5132/");
|
options.SetIssuer("http://localhost:5132/");
|
||||||
@ -70,8 +78,8 @@ builder.Services.AddCors(options =>
|
|||||||
options.AddPolicy("AllowAll", policy =>
|
options.AddPolicy("AllowAll", policy =>
|
||||||
{
|
{
|
||||||
policy.AllowAnyOrigin()
|
policy.AllowAnyOrigin()
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
.AllowAnyHeader();
|
.AllowAnyHeader();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,6 +87,7 @@ builder.Services.AddEndpointsApiExplorer();
|
|||||||
builder.Services.AddSwaggerGen(c =>
|
builder.Services.AddSwaggerGen(c =>
|
||||||
{
|
{
|
||||||
c.SwaggerDoc("v1", new() { Title = "Fengling.Console API", Version = "v1" });
|
c.SwaggerDoc("v1", new() { Title = "Fengling.Console API", Version = "v1" });
|
||||||
|
c.CustomSchemaIds(type => type.FullName);
|
||||||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
||||||
if (File.Exists(xmlPath))
|
if (File.Exists(xmlPath))
|
||||||
@ -87,13 +96,14 @@ builder.Services.AddSwaggerGen(c =>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Services.AddRepositories(typeof(PlatformDbContext).Assembly);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
app.UseSwaggerUI(c =>
|
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Fengling.Console API V1"); });
|
||||||
{
|
|
||||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Fengling.Console API V1");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseCors("AllowAll");
|
app.UseCors("AllowAll");
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
using Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Repositories;
|
|
||||||
|
|
||||||
public interface IRoleRepository
|
|
||||||
{
|
|
||||||
Task<ApplicationRole?> GetByIdAsync(long id);
|
|
||||||
Task<ApplicationRole?> GetByNameAsync(string name);
|
|
||||||
Task<IEnumerable<ApplicationRole>> GetAllAsync();
|
|
||||||
Task<IEnumerable<ApplicationRole>> GetPagedAsync(int page, int pageSize, string? name = null, string? tenantId = null);
|
|
||||||
Task<int> CountAsync(string? name = null, string? tenantId = null);
|
|
||||||
Task AddAsync(ApplicationRole role);
|
|
||||||
Task UpdateAsync(ApplicationRole role);
|
|
||||||
Task DeleteAsync(ApplicationRole role);
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
using Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Repositories;
|
|
||||||
|
|
||||||
public interface ITenantRepository
|
|
||||||
{
|
|
||||||
Task<Tenant?> GetByIdAsync(long id);
|
|
||||||
Task<Tenant?> GetByTenantIdAsync(string tenantId);
|
|
||||||
Task<IEnumerable<Tenant>> GetAllAsync();
|
|
||||||
Task<IEnumerable<Tenant>> GetPagedAsync(int page, int pageSize, string? name = null, string? tenantId = null, string? status = null);
|
|
||||||
Task<int> CountAsync(string? name = null, string? tenantId = null, string? status = null);
|
|
||||||
Task AddAsync(Tenant tenant);
|
|
||||||
Task UpdateAsync(Tenant tenant);
|
|
||||||
Task DeleteAsync(Tenant tenant);
|
|
||||||
Task<int> GetUserCountAsync(long tenantId);
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
using Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Repositories;
|
|
||||||
|
|
||||||
public interface IUserRepository
|
|
||||||
{
|
|
||||||
Task<ApplicationUser?> GetByIdAsync(long id);
|
|
||||||
Task<ApplicationUser?> GetByUserNameAsync(string userName);
|
|
||||||
Task<IEnumerable<ApplicationUser>> GetAllAsync();
|
|
||||||
Task<IEnumerable<ApplicationUser>> GetPagedAsync(int page, int pageSize, string? userName = null, string? email = null, string? tenantId = null);
|
|
||||||
Task<int> CountAsync(string? userName = null, string? email = null, string? tenantId = null);
|
|
||||||
Task AddAsync(ApplicationUser user);
|
|
||||||
Task UpdateAsync(ApplicationUser user);
|
|
||||||
Task DeleteAsync(ApplicationUser user);
|
|
||||||
}
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
using Fengling.Console.Datas;
|
|
||||||
using Fengling.Console.Models.Entities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Repositories;
|
|
||||||
|
|
||||||
public class RoleRepository(ApplicationDbContext context) : IRoleRepository
|
|
||||||
{
|
|
||||||
public async Task<ApplicationRole?> GetByIdAsync(long id)
|
|
||||||
{
|
|
||||||
return await context.Roles.FindAsync(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ApplicationRole?> GetByNameAsync(string name)
|
|
||||||
{
|
|
||||||
return await context.Roles.FirstOrDefaultAsync(r => r.Name == name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<ApplicationRole>> GetAllAsync()
|
|
||||||
{
|
|
||||||
return await context.Roles.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<ApplicationRole>> GetPagedAsync(int page, int pageSize, string? name = null,
|
|
||||||
string? tenantId = null)
|
|
||||||
{
|
|
||||||
var query = context.Roles.AsQueryable();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
query = query.Where(r => r.Name != null && r.Name.Contains(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
|
||||||
{
|
|
||||||
query = query.Where(r => r.TenantId.ToString() == tenantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await query
|
|
||||||
.OrderByDescending(r => r.CreatedTime)
|
|
||||||
.Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> CountAsync(string? name = null, string? tenantId = null)
|
|
||||||
{
|
|
||||||
var query = context.Roles.AsQueryable();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
query = query.Where(r => r.Name != null && r.Name.Contains(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
|
||||||
{
|
|
||||||
query = query.Where(r => r.TenantId.ToString() == tenantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await query.CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task AddAsync(ApplicationRole role)
|
|
||||||
{
|
|
||||||
context.Roles.Add(role);
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task UpdateAsync(ApplicationRole role)
|
|
||||||
{
|
|
||||||
context.Roles.Update(role);
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteAsync(ApplicationRole role)
|
|
||||||
{
|
|
||||||
context.Roles.Remove(role);
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
using Fengling.Console.Datas;
|
|
||||||
using Fengling.Console.Models.Entities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Repositories;
|
|
||||||
|
|
||||||
public class TenantRepository(ApplicationDbContext context) : ITenantRepository
|
|
||||||
{
|
|
||||||
public async Task<Tenant?> GetByIdAsync(long id)
|
|
||||||
{
|
|
||||||
return await context.Tenants.FindAsync(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Tenant?> GetByTenantIdAsync(string tenantId)
|
|
||||||
{
|
|
||||||
return await context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<Tenant>> GetAllAsync()
|
|
||||||
{
|
|
||||||
return await context.Tenants.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<Tenant>> GetPagedAsync(int page, int pageSize, string? name = null,
|
|
||||||
string? tenantId = null, string? status = null)
|
|
||||||
{
|
|
||||||
var query = context.Tenants.AsQueryable();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
query = query.Where(t => t.Name.Contains(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
|
||||||
{
|
|
||||||
query = query.Where(t => t.TenantId.Contains(tenantId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(status))
|
|
||||||
{
|
|
||||||
query = query.Where(t => t.Status == status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await query
|
|
||||||
.OrderByDescending(t => t.CreatedAt)
|
|
||||||
.Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> CountAsync(string? name = null, string? tenantId = null, string? status = null)
|
|
||||||
{
|
|
||||||
var query = context.Tenants.AsQueryable();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
query = query.Where(t => t.Name.Contains(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
|
||||||
{
|
|
||||||
query = query.Where(t => t.TenantId.Contains(tenantId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(status))
|
|
||||||
{
|
|
||||||
query = query.Where(t => t.Status == status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await query.CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task AddAsync(Tenant tenant)
|
|
||||||
{
|
|
||||||
context.Tenants.Add(tenant);
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task UpdateAsync(Tenant tenant)
|
|
||||||
{
|
|
||||||
context.Tenants.Update(tenant);
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteAsync(Tenant tenant)
|
|
||||||
{
|
|
||||||
context.Tenants.Remove(tenant);
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> GetUserCountAsync(long tenantId)
|
|
||||||
{
|
|
||||||
return await context.Users.CountAsync(u => u.TenantInfo.Id == tenantId && !u.IsDeleted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
using Fengling.Console.Datas;
|
|
||||||
using Fengling.Console.Models.Entities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Repositories;
|
|
||||||
|
|
||||||
public class UserRepository : IUserRepository
|
|
||||||
{
|
|
||||||
private readonly ApplicationDbContext _context;
|
|
||||||
|
|
||||||
public UserRepository(ApplicationDbContext context)
|
|
||||||
{
|
|
||||||
_context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ApplicationUser?> GetByIdAsync(long id)
|
|
||||||
{
|
|
||||||
return await _context.Users.FindAsync(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ApplicationUser?> GetByUserNameAsync(string userName)
|
|
||||||
{
|
|
||||||
return await _context.Users.FirstOrDefaultAsync(u => u.UserName == userName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<ApplicationUser>> GetAllAsync()
|
|
||||||
{
|
|
||||||
return await _context.Users.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<ApplicationUser>> GetPagedAsync(int page, int pageSize, string? userName = null, string? email = null, string? tenantId = null)
|
|
||||||
{
|
|
||||||
var query = _context.Users.AsQueryable();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(userName))
|
|
||||||
{
|
|
||||||
query = query.Where(u => u.UserName != null && u.UserName.Contains(userName));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(email))
|
|
||||||
{
|
|
||||||
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
|
||||||
{
|
|
||||||
query = query.Where(u => u.TenantInfo.Id.ToString() == tenantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await query
|
|
||||||
.OrderByDescending(u => u.CreatedTime)
|
|
||||||
.Skip((page - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> CountAsync(string? userName = null, string? email = null, string? tenantId = null)
|
|
||||||
{
|
|
||||||
var query = _context.Users.AsQueryable();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(userName))
|
|
||||||
{
|
|
||||||
query = query.Where(u => u.UserName != null && u.UserName.Contains(userName));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(email))
|
|
||||||
{
|
|
||||||
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
|
||||||
{
|
|
||||||
query = query.Where(u => u.TenantInfo.Id.ToString() == tenantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await query.CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task AddAsync(ApplicationUser user)
|
|
||||||
{
|
|
||||||
_context.Users.Add(user);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task UpdateAsync(ApplicationUser user)
|
|
||||||
{
|
|
||||||
_context.Users.Update(user);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteAsync(ApplicationUser user)
|
|
||||||
{
|
|
||||||
_context.Users.Remove(user);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -24,21 +24,19 @@ public interface IGatewayService
|
|||||||
|
|
||||||
public class GatewayService : IGatewayService
|
public class GatewayService : IGatewayService
|
||||||
{
|
{
|
||||||
private readonly IDbContextFactory<GatewayDbContext> _dbContextFactory;
|
private readonly GatewayDbContext _dbContext;
|
||||||
private readonly ILogger<GatewayService> _logger;
|
private readonly ILogger<GatewayService> _logger;
|
||||||
|
|
||||||
public GatewayService(IDbContextFactory<GatewayDbContext> dbContextFactory, ILogger<GatewayService> logger)
|
public GatewayService(GatewayDbContext dbContext, ILogger<GatewayService> logger)
|
||||||
{
|
{
|
||||||
_dbContextFactory = dbContextFactory;
|
_dbContext = dbContext;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<GatewayStatisticsDto> GetStatisticsAsync()
|
public async Task<GatewayStatisticsDto> GetStatisticsAsync()
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var routes = await _dbContext.TenantRoutes.Where(r => !r.IsDeleted).ToListAsync();
|
||||||
|
var instances = await _dbContext.ServiceInstances.Where(i => !i.IsDeleted).ToListAsync();
|
||||||
var routes = await db.TenantRoutes.Where(r => !r.IsDeleted).ToListAsync();
|
|
||||||
var instances = await db.ServiceInstances.Where(i => !i.IsDeleted).ToListAsync();
|
|
||||||
|
|
||||||
return new GatewayStatisticsDto
|
return new GatewayStatisticsDto
|
||||||
{
|
{
|
||||||
@ -57,9 +55,7 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<List<GatewayServiceDto>> GetServicesAsync(bool globalOnly = false, string? tenantCode = null)
|
public async Task<List<GatewayServiceDto>> GetServicesAsync(bool globalOnly = false, string? tenantCode = null)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var query = _dbContext.TenantRoutes.Where(r => !r.IsDeleted);
|
||||||
|
|
||||||
var query = db.TenantRoutes.Where(r => !r.IsDeleted);
|
|
||||||
|
|
||||||
if (globalOnly)
|
if (globalOnly)
|
||||||
query = query.Where(r => r.IsGlobal);
|
query = query.Where(r => r.IsGlobal);
|
||||||
@ -69,7 +65,7 @@ public class GatewayService : IGatewayService
|
|||||||
var routes = await query.OrderByDescending(r => r.CreatedTime).ToListAsync();
|
var routes = await query.OrderByDescending(r => r.CreatedTime).ToListAsync();
|
||||||
var clusters = routes.Select(r => r.ClusterId).Distinct().ToList();
|
var clusters = routes.Select(r => r.ClusterId).Distinct().ToList();
|
||||||
|
|
||||||
var instances = await db.ServiceInstances
|
var instances = await _dbContext.ServiceInstances
|
||||||
.Where(i => clusters.Contains(i.ClusterId) && !i.IsDeleted)
|
.Where(i => clusters.Contains(i.ClusterId) && !i.IsDeleted)
|
||||||
.GroupBy(i => i.ClusterId)
|
.GroupBy(i => i.ClusterId)
|
||||||
.ToDictionaryAsync(g => g.Key, g => g.Count());
|
.ToDictionaryAsync(g => g.Key, g => g.Count());
|
||||||
@ -79,9 +75,7 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<GatewayServiceDto?> GetServiceAsync(string serviceName, string? tenantCode = null)
|
public async Task<GatewayServiceDto?> GetServiceAsync(string serviceName, string? tenantCode = null)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var route = await _dbContext.TenantRoutes
|
||||||
|
|
||||||
var route = await db.TenantRoutes
|
|
||||||
.FirstOrDefaultAsync(r =>
|
.FirstOrDefaultAsync(r =>
|
||||||
r.ServiceName == serviceName &&
|
r.ServiceName == serviceName &&
|
||||||
r.IsDeleted == false &&
|
r.IsDeleted == false &&
|
||||||
@ -89,7 +83,7 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
if (route == null) return null;
|
if (route == null) return null;
|
||||||
|
|
||||||
var instances = await db.ServiceInstances
|
var instances = await _dbContext.ServiceInstances
|
||||||
.CountAsync(i => i.ClusterId == route.ClusterId && !i.IsDeleted);
|
.CountAsync(i => i.ClusterId == route.ClusterId && !i.IsDeleted);
|
||||||
|
|
||||||
return MapToServiceDto(route, instances);
|
return MapToServiceDto(route, instances);
|
||||||
@ -97,8 +91,6 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<GatewayServiceDto> RegisterServiceAsync(CreateGatewayServiceDto dto)
|
public async Task<GatewayServiceDto> RegisterServiceAsync(CreateGatewayServiceDto dto)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
|
||||||
|
|
||||||
var clusterId = $"{dto.ServicePrefix}-service";
|
var clusterId = $"{dto.ServicePrefix}-service";
|
||||||
var pathPattern = $"/{dto.ServicePrefix}/{dto.Version}/{{**path}}";
|
var pathPattern = $"/{dto.ServicePrefix}/{dto.Version}/{{**path}}";
|
||||||
var destinationId = string.IsNullOrEmpty(dto.DestinationId)
|
var destinationId = string.IsNullOrEmpty(dto.DestinationId)
|
||||||
@ -106,7 +98,7 @@ public class GatewayService : IGatewayService
|
|||||||
: dto.DestinationId;
|
: dto.DestinationId;
|
||||||
|
|
||||||
// Check if route already exists
|
// Check if route already exists
|
||||||
var existingRoute = await db.TenantRoutes
|
var existingRoute = await _dbContext.TenantRoutes
|
||||||
.FirstOrDefaultAsync(r =>
|
.FirstOrDefaultAsync(r =>
|
||||||
r.ServiceName == dto.ServicePrefix &&
|
r.ServiceName == dto.ServicePrefix &&
|
||||||
r.IsGlobal == dto.IsGlobal &&
|
r.IsGlobal == dto.IsGlobal &&
|
||||||
@ -130,7 +122,7 @@ public class GatewayService : IGatewayService
|
|||||||
Status = 1,
|
Status = 1,
|
||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
await db.ServiceInstances.AddAsync(instance);
|
await _dbContext.ServiceInstances.AddAsync(instance);
|
||||||
|
|
||||||
// Add route
|
// Add route
|
||||||
var routeId = instanceId + 1;
|
var routeId = instanceId + 1;
|
||||||
@ -146,9 +138,9 @@ public class GatewayService : IGatewayService
|
|||||||
IsGlobal = dto.IsGlobal,
|
IsGlobal = dto.IsGlobal,
|
||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
await db.TenantRoutes.AddAsync(route);
|
await _dbContext.TenantRoutes.AddAsync(route);
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
_logger.LogInformation("Registered service {Service} at {Address}", dto.ServicePrefix, dto.ServiceAddress);
|
_logger.LogInformation("Registered service {Service} at {Address}", dto.ServicePrefix, dto.ServiceAddress);
|
||||||
|
|
||||||
@ -157,9 +149,7 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<bool> UnregisterServiceAsync(string serviceName, string? tenantCode = null)
|
public async Task<bool> UnregisterServiceAsync(string serviceName, string? tenantCode = null)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var route = await _dbContext.TenantRoutes
|
||||||
|
|
||||||
var route = await db.TenantRoutes
|
|
||||||
.FirstOrDefaultAsync(r =>
|
.FirstOrDefaultAsync(r =>
|
||||||
r.ServiceName == serviceName &&
|
r.ServiceName == serviceName &&
|
||||||
r.IsDeleted == false &&
|
r.IsDeleted == false &&
|
||||||
@ -172,7 +162,7 @@ public class GatewayService : IGatewayService
|
|||||||
route.UpdatedTime = DateTime.UtcNow;
|
route.UpdatedTime = DateTime.UtcNow;
|
||||||
|
|
||||||
// Soft delete instances
|
// Soft delete instances
|
||||||
var instances = await db.ServiceInstances
|
var instances = await _dbContext.ServiceInstances
|
||||||
.Where(i => i.ClusterId == route.ClusterId && !i.IsDeleted)
|
.Where(i => i.ClusterId == route.ClusterId && !i.IsDeleted)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@ -182,7 +172,7 @@ public class GatewayService : IGatewayService
|
|||||||
instance.UpdatedTime = DateTime.UtcNow;
|
instance.UpdatedTime = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
_logger.LogInformation("Unregistered service {Service}", serviceName);
|
_logger.LogInformation("Unregistered service {Service}", serviceName);
|
||||||
|
|
||||||
@ -191,9 +181,7 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<List<GatewayRouteDto>> GetRoutesAsync(bool globalOnly = false)
|
public async Task<List<GatewayRouteDto>> GetRoutesAsync(bool globalOnly = false)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var query = _dbContext.TenantRoutes.Where(r => !r.IsDeleted);
|
||||||
|
|
||||||
var query = db.TenantRoutes.Where(r => !r.IsDeleted);
|
|
||||||
|
|
||||||
if (globalOnly)
|
if (globalOnly)
|
||||||
query = query.Where(r => r.IsGlobal);
|
query = query.Where(r => r.IsGlobal);
|
||||||
@ -201,7 +189,7 @@ public class GatewayService : IGatewayService
|
|||||||
var routes = await query.OrderByDescending(r => r.Priority).ToListAsync();
|
var routes = await query.OrderByDescending(r => r.Priority).ToListAsync();
|
||||||
var clusters = routes.Select(r => r.ClusterId).Distinct().ToList();
|
var clusters = routes.Select(r => r.ClusterId).Distinct().ToList();
|
||||||
|
|
||||||
var instances = await db.ServiceInstances
|
var instances = await _dbContext.ServiceInstances
|
||||||
.Where(i => clusters.Contains(i.ClusterId) && !i.IsDeleted)
|
.Where(i => clusters.Contains(i.ClusterId) && !i.IsDeleted)
|
||||||
.GroupBy(i => i.ClusterId)
|
.GroupBy(i => i.ClusterId)
|
||||||
.ToDictionaryAsync(g => g.Key, g => g.Count());
|
.ToDictionaryAsync(g => g.Key, g => g.Count());
|
||||||
@ -222,9 +210,7 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<GatewayRouteDto> CreateRouteAsync(CreateGatewayRouteDto dto)
|
public async Task<GatewayRouteDto> CreateRouteAsync(CreateGatewayRouteDto dto)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var existing = await _dbContext.TenantRoutes
|
||||||
|
|
||||||
var existing = await db.TenantRoutes
|
|
||||||
.FirstOrDefaultAsync(r =>
|
.FirstOrDefaultAsync(r =>
|
||||||
r.ServiceName == dto.ServiceName &&
|
r.ServiceName == dto.ServiceName &&
|
||||||
r.IsGlobal == dto.IsGlobal &&
|
r.IsGlobal == dto.IsGlobal &&
|
||||||
@ -248,8 +234,8 @@ public class GatewayService : IGatewayService
|
|||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.TenantRoutes.AddAsync(route);
|
await _dbContext.TenantRoutes.AddAsync(route);
|
||||||
await db.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
return new GatewayRouteDto
|
return new GatewayRouteDto
|
||||||
{
|
{
|
||||||
@ -267,9 +253,7 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<List<GatewayInstanceDto>> GetInstancesAsync(string clusterId)
|
public async Task<List<GatewayInstanceDto>> GetInstancesAsync(string clusterId)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var instances = await _dbContext.ServiceInstances
|
||||||
|
|
||||||
var instances = await db.ServiceInstances
|
|
||||||
.Where(i => i.ClusterId == clusterId && !i.IsDeleted)
|
.Where(i => i.ClusterId == clusterId && !i.IsDeleted)
|
||||||
.OrderByDescending(i => i.Weight)
|
.OrderByDescending(i => i.Weight)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
@ -289,9 +273,7 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<GatewayInstanceDto> AddInstanceAsync(CreateGatewayInstanceDto dto)
|
public async Task<GatewayInstanceDto> AddInstanceAsync(CreateGatewayInstanceDto dto)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var existing = await _dbContext.ServiceInstances
|
||||||
|
|
||||||
var existing = await db.ServiceInstances
|
|
||||||
.FirstOrDefaultAsync(i =>
|
.FirstOrDefaultAsync(i =>
|
||||||
i.ClusterId == dto.ClusterId &&
|
i.ClusterId == dto.ClusterId &&
|
||||||
i.DestinationId == dto.DestinationId &&
|
i.DestinationId == dto.DestinationId &&
|
||||||
@ -314,8 +296,8 @@ public class GatewayService : IGatewayService
|
|||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.ServiceInstances.AddAsync(instance);
|
await _dbContext.ServiceInstances.AddAsync(instance);
|
||||||
await db.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
return new GatewayInstanceDto
|
return new GatewayInstanceDto
|
||||||
{
|
{
|
||||||
@ -332,29 +314,25 @@ public class GatewayService : IGatewayService
|
|||||||
|
|
||||||
public async Task<bool> RemoveInstanceAsync(long instanceId)
|
public async Task<bool> RemoveInstanceAsync(long instanceId)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var instance = await _dbContext.ServiceInstances.FindAsync(instanceId);
|
||||||
|
|
||||||
var instance = await db.ServiceInstances.FindAsync(instanceId);
|
|
||||||
if (instance == null) return false;
|
if (instance == null) return false;
|
||||||
|
|
||||||
instance.IsDeleted = true;
|
instance.IsDeleted = true;
|
||||||
instance.UpdatedTime = DateTime.UtcNow;
|
instance.UpdatedTime = DateTime.UtcNow;
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> UpdateInstanceWeightAsync(long instanceId, int weight)
|
public async Task<bool> UpdateInstanceWeightAsync(long instanceId, int weight)
|
||||||
{
|
{
|
||||||
await using var db = await _dbContextFactory.CreateDbContextAsync();
|
var instance = await _dbContext.ServiceInstances.FindAsync(instanceId);
|
||||||
|
|
||||||
var instance = await db.ServiceInstances.FindAsync(instanceId);
|
|
||||||
if (instance == null) return false;
|
if (instance == null) return false;
|
||||||
|
|
||||||
instance.Weight = weight;
|
instance.Weight = weight;
|
||||||
instance.UpdatedTime = DateTime.UtcNow;
|
instance.UpdatedTime = DateTime.UtcNow;
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
55
Services/H5LinkService.cs
Normal file
55
Services/H5LinkService.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using QRCoder;
|
||||||
|
|
||||||
|
namespace Fengling.Console.Services;
|
||||||
|
|
||||||
|
public interface IH5LinkService
|
||||||
|
{
|
||||||
|
Task<H5LinkResult> GenerateH5LinkAsync(int tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class H5LinkResult
|
||||||
|
{
|
||||||
|
public string Link { get; set; } = string.Empty;
|
||||||
|
public string QrCodeBase64 { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class H5LinkService : IH5LinkService
|
||||||
|
{
|
||||||
|
private readonly ITenantManager _tenantManager;
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
|
public H5LinkService(ITenantManager tenantManager, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_tenantManager = tenantManager;
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<H5LinkResult> GenerateH5LinkAsync(int tenantId)
|
||||||
|
{
|
||||||
|
var tenant = await _tenantManager.FindByIdAsync(tenantId)
|
||||||
|
?? throw new KeyNotFoundException($"Tenant with ID {tenantId} not found");
|
||||||
|
|
||||||
|
var link = GenerateLink(tenant);
|
||||||
|
var qrCodeBase64 = GenerateQrCode(link);
|
||||||
|
|
||||||
|
return new H5LinkResult
|
||||||
|
{
|
||||||
|
Link = link,
|
||||||
|
QrCodeBase64 = qrCodeBase64
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateLink(Fengling.Platform.Domain.AggregatesModel.TenantAggregate.Tenant tenant)
|
||||||
|
{
|
||||||
|
var baseUrl = _configuration["AppSettings:DefaultH5BaseUrl"] ?? "https://h5.example.com";
|
||||||
|
return $"{baseUrl.TrimEnd('/')}/{tenant.TenantCode}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateQrCode(string content)
|
||||||
|
{
|
||||||
|
byte[] qrCodeBytes = PngByteQRCodeHelper.GetQRCode(content, QRCodeGenerator.ECCLevel.M, 20);
|
||||||
|
return Convert.ToBase64String(qrCodeBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -45,10 +45,10 @@ public class OAuthClientService : IOAuthClientService
|
|||||||
var clientIdValue = await _applicationManager.GetClientIdAsync(application);
|
var clientIdValue = await _applicationManager.GetClientIdAsync(application);
|
||||||
var displayNameValue = await _applicationManager.GetDisplayNameAsync(application);
|
var displayNameValue = await _applicationManager.GetDisplayNameAsync(application);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(displayName) && !displayNameValue.Contains(displayName, StringComparison.OrdinalIgnoreCase))
|
if (!string.IsNullOrEmpty(displayName) && (string.IsNullOrEmpty(displayNameValue) || !displayNameValue.Contains(displayName, StringComparison.OrdinalIgnoreCase)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(clientId) && !clientIdValue.Contains(clientId, StringComparison.OrdinalIgnoreCase))
|
if (!string.IsNullOrEmpty(clientId) && (string.IsNullOrEmpty(clientIdValue) || !clientIdValue.Contains(clientId, StringComparison.OrdinalIgnoreCase)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var clientType = await _applicationManager.GetClientTypeAsync(application);
|
var clientType = await _applicationManager.GetClientTypeAsync(application);
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
using Fengling.Console.Models.Dtos;
|
using Fengling.Console.Models.Dtos;
|
||||||
using Fengling.Console.Repositories;
|
using Fengling.Platform.Domain.AggregatesModel.UserAggregate;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.RoleAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Fengling.Console.Datas;
|
|
||||||
using Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Services;
|
namespace Fengling.Console.Services;
|
||||||
|
|
||||||
@ -23,20 +24,20 @@ public interface IRoleService
|
|||||||
|
|
||||||
public class RoleService : IRoleService
|
public class RoleService : IRoleService
|
||||||
{
|
{
|
||||||
private readonly IRoleRepository _repository;
|
private readonly ITenantManager _tenantManager;
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly RoleManager<ApplicationRole> _roleManager;
|
private readonly RoleManager<ApplicationRole> _roleManager;
|
||||||
private readonly ApplicationDbContext _context;
|
private readonly PlatformDbContext _context;
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
|
||||||
public RoleService(
|
public RoleService(
|
||||||
IRoleRepository repository,
|
ITenantManager tenantManager,
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
RoleManager<ApplicationRole> roleManager,
|
RoleManager<ApplicationRole> roleManager,
|
||||||
ApplicationDbContext context,
|
PlatformDbContext context,
|
||||||
IHttpContextAccessor httpContextAccessor)
|
IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
_repository = repository;
|
_tenantManager = tenantManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_roleManager = roleManager;
|
_roleManager = roleManager;
|
||||||
_context = context;
|
_context = context;
|
||||||
@ -46,8 +47,24 @@ public class RoleService : IRoleService
|
|||||||
public async Task<(IEnumerable<RoleDto> Items, int TotalCount)> GetRolesAsync(int page, int pageSize,
|
public async Task<(IEnumerable<RoleDto> Items, int TotalCount)> GetRolesAsync(int page, int pageSize,
|
||||||
string? name = null, string? tenantId = null)
|
string? name = null, string? tenantId = null)
|
||||||
{
|
{
|
||||||
var roles = await _repository.GetPagedAsync(page, pageSize, name, tenantId);
|
var query = _context.Roles.AsQueryable();
|
||||||
var totalCount = await _repository.CountAsync(name, tenantId);
|
|
||||||
|
if (!string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
query = query.Where(r => r.Name != null && r.Name.Contains(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(tenantId))
|
||||||
|
{
|
||||||
|
query = query.Where(r => r.TenantId.HasValue && r.TenantId.Value.ToString().Contains(tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalCount = await query.CountAsync();
|
||||||
|
var roles = await query
|
||||||
|
.OrderByDescending(r => r.CreatedTime)
|
||||||
|
.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
var roleDtos = new List<RoleDto>();
|
var roleDtos = new List<RoleDto>();
|
||||||
foreach (var role in roles)
|
foreach (var role in roles)
|
||||||
@ -72,7 +89,7 @@ public class RoleService : IRoleService
|
|||||||
|
|
||||||
public async Task<RoleDto?> GetRoleAsync(long id)
|
public async Task<RoleDto?> GetRoleAsync(long id)
|
||||||
{
|
{
|
||||||
var role = await _repository.GetByIdAsync(id);
|
var role = await _context.Roles.FindAsync(id);
|
||||||
if (role == null) return null;
|
if (role == null) return null;
|
||||||
|
|
||||||
return new RoleDto
|
return new RoleDto
|
||||||
@ -91,7 +108,7 @@ public class RoleService : IRoleService
|
|||||||
|
|
||||||
public async Task<IEnumerable<UserDto>> GetRoleUsersAsync(long id)
|
public async Task<IEnumerable<UserDto>> GetRoleUsersAsync(long id)
|
||||||
{
|
{
|
||||||
var role = await _repository.GetByIdAsync(id);
|
var role = await _context.Roles.FindAsync(id);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Role with ID {id} not found");
|
throw new KeyNotFoundException($"Role with ID {id} not found");
|
||||||
@ -103,14 +120,15 @@ public class RoleService : IRoleService
|
|||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
var roles = await _userManager.GetRolesAsync(user);
|
var roles = await _userManager.GetRolesAsync(user);
|
||||||
|
var tenant = user.TenantInfo?.TenantId > 0 ? await _tenantManager.FindByIdAsync(user.TenantInfo.TenantId) : null;
|
||||||
userDtos.Add(new UserDto
|
userDtos.Add(new UserDto
|
||||||
{
|
{
|
||||||
Id = user.Id,
|
Id = user.Id,
|
||||||
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 = tenant?.Name ?? "",
|
||||||
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,
|
||||||
@ -128,7 +146,7 @@ public class RoleService : IRoleService
|
|||||||
Name = dto.Name,
|
Name = dto.Name,
|
||||||
DisplayName = dto.DisplayName,
|
DisplayName = dto.DisplayName,
|
||||||
Description = dto.Description,
|
Description = dto.Description,
|
||||||
TenantId = dto.TenantId,
|
TenantId = dto.TenantId.HasValue ? dto.TenantId.Value : null,
|
||||||
Permissions = dto.Permissions,
|
Permissions = dto.Permissions,
|
||||||
IsSystem = false,
|
IsSystem = false,
|
||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
@ -159,7 +177,7 @@ public class RoleService : IRoleService
|
|||||||
|
|
||||||
public async Task<RoleDto> UpdateRoleAsync(long id, UpdateRoleDto dto)
|
public async Task<RoleDto> UpdateRoleAsync(long id, UpdateRoleDto dto)
|
||||||
{
|
{
|
||||||
var role = await _repository.GetByIdAsync(id);
|
var role = await _context.Roles.FindAsync(id);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Role with ID {id} not found");
|
throw new KeyNotFoundException($"Role with ID {id} not found");
|
||||||
@ -176,7 +194,7 @@ public class RoleService : IRoleService
|
|||||||
role.Description = dto.Description;
|
role.Description = dto.Description;
|
||||||
role.Permissions = dto.Permissions;
|
role.Permissions = dto.Permissions;
|
||||||
|
|
||||||
await _repository.UpdateAsync(role);
|
await _roleManager.UpdateAsync(role);
|
||||||
|
|
||||||
await CreateAuditLog("role", "update", "Role", role.Id, role.DisplayName, oldValue,
|
await CreateAuditLog("role", "update", "Role", role.Id, role.DisplayName, oldValue,
|
||||||
System.Text.Json.JsonSerializer.Serialize(role));
|
System.Text.Json.JsonSerializer.Serialize(role));
|
||||||
@ -198,7 +216,7 @@ public class RoleService : IRoleService
|
|||||||
|
|
||||||
public async Task DeleteRoleAsync(long id)
|
public async Task DeleteRoleAsync(long id)
|
||||||
{
|
{
|
||||||
var role = await _repository.GetByIdAsync(id);
|
var role = await _context.Roles.FindAsync(id);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Role with ID {id} not found");
|
throw new KeyNotFoundException($"Role with ID {id} not found");
|
||||||
@ -217,14 +235,14 @@ public class RoleService : IRoleService
|
|||||||
await _userManager.RemoveFromRoleAsync(user, role.Name!);
|
await _userManager.RemoveFromRoleAsync(user, role.Name!);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _repository.DeleteAsync(role);
|
await _roleManager.DeleteAsync(role);
|
||||||
|
|
||||||
await CreateAuditLog("role", "delete", "Role", role.Id, role.DisplayName, oldValue);
|
await CreateAuditLog("role", "delete", "Role", role.Id, role.DisplayName, oldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddUserToRoleAsync(long roleId, long userId)
|
public async Task AddUserToRoleAsync(long roleId, long userId)
|
||||||
{
|
{
|
||||||
var role = await _repository.GetByIdAsync(roleId);
|
var role = await _context.Roles.FindAsync(roleId);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Role with ID {roleId} not found");
|
throw new KeyNotFoundException($"Role with ID {roleId} not found");
|
||||||
@ -247,7 +265,7 @@ public class RoleService : IRoleService
|
|||||||
|
|
||||||
public async Task RemoveUserFromRoleAsync(long roleId, long userId)
|
public async Task RemoveUserFromRoleAsync(long roleId, long userId)
|
||||||
{
|
{
|
||||||
var role = await _repository.GetByIdAsync(roleId);
|
var role = await _context.Roles.FindAsync(roleId);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Role with ID {roleId} not found");
|
throw new KeyNotFoundException($"Role with ID {roleId} not found");
|
||||||
|
|||||||
@ -1,15 +1,19 @@
|
|||||||
using Fengling.Console.Models.Dtos;
|
using Fengling.Console.Models.Dtos;
|
||||||
using Fengling.Console.Repositories;
|
using Fengling.Platform.Domain.AggregatesModel.UserAggregate;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.RoleAggregate;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Fengling.Console.Datas;
|
using TenantStatus = Fengling.Platform.Domain.AggregatesModel.TenantAggregate.TenantStatus;
|
||||||
using Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
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);
|
||||||
@ -21,27 +25,27 @@ public interface ITenantService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class TenantService(
|
public class TenantService(
|
||||||
ITenantRepository repository,
|
ITenantManager tenantManager,
|
||||||
IUserRepository userRepository,
|
|
||||||
IRoleRepository roleRepository,
|
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
ApplicationDbContext context,
|
RoleManager<ApplicationRole> roleManager,
|
||||||
|
PlatformDbContext context,
|
||||||
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 tenantManager.GetPagedAsync(page, pageSize, name, tenantCode, status);
|
||||||
var totalCount = await repository.CountAsync(name, tenantId, status);
|
var totalCount = await tenantManager.GetCountAsync(name, tenantCode, status);
|
||||||
|
|
||||||
var tenantDtos = new List<TenantDto>();
|
var tenantDtos = new List<TenantDto>();
|
||||||
foreach (var tenant in tenants)
|
foreach (var tenant in tenants)
|
||||||
{
|
{
|
||||||
var userCount = await repository.GetUserCountAsync(tenant.Id);
|
var userCount = await tenantManager.GetUserCountAsync(tenant.Id);
|
||||||
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,
|
||||||
@ -60,19 +64,19 @@ public class TenantService(
|
|||||||
|
|
||||||
public async Task<TenantDto?> GetTenantAsync(long id)
|
public async Task<TenantDto?> GetTenantAsync(long id)
|
||||||
{
|
{
|
||||||
var tenant = await repository.GetByIdAsync(id);
|
var tenant = await tenantManager.FindByIdAsync(id);
|
||||||
if (tenant == null) return null;
|
if (tenant == null) return null;
|
||||||
|
|
||||||
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,
|
||||||
ContactPhone = tenant.ContactPhone,
|
ContactPhone = tenant.ContactPhone,
|
||||||
MaxUsers = tenant.MaxUsers,
|
MaxUsers = tenant.MaxUsers,
|
||||||
UserCount = await repository.GetUserCountAsync(tenant.Id),
|
UserCount = await tenantManager.GetUserCountAsync(tenant.Id),
|
||||||
Status = tenant.Status,
|
Status = tenant.Status,
|
||||||
ExpiresAt = tenant.ExpiresAt,
|
ExpiresAt = tenant.ExpiresAt,
|
||||||
Description = tenant.Description,
|
Description = tenant.Description,
|
||||||
@ -82,13 +86,16 @@ public class TenantService(
|
|||||||
|
|
||||||
public async Task<IEnumerable<UserDto>> GetTenantUsersAsync(long tenantId)
|
public async Task<IEnumerable<UserDto>> GetTenantUsersAsync(long tenantId)
|
||||||
{
|
{
|
||||||
var tenant = await repository.GetByIdAsync(tenantId);
|
var tenant = await tenantManager.FindByIdAsync(tenantId);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Tenant with ID {tenantId} not found");
|
throw new KeyNotFoundException($"Tenant with ID {tenantId} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
var users = await userRepository.GetPagedAsync(1, int.MaxValue, null, null, tenantId.ToString());
|
var users = await context.Users
|
||||||
|
.Where(u => u.TenantInfo!.TenantId == tenantId)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
var userDtos = new List<UserDto>();
|
var userDtos = new List<UserDto>();
|
||||||
|
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
@ -100,8 +107,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.TenantId.ToString(),
|
||||||
TenantName = user.TenantInfo.Name,
|
TenantName = tenant?.Name ?? "",
|
||||||
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,
|
||||||
@ -114,13 +121,16 @@ public class TenantService(
|
|||||||
|
|
||||||
public async Task<IEnumerable<object>> GetTenantRolesAsync(long tenantId)
|
public async Task<IEnumerable<object>> GetTenantRolesAsync(long tenantId)
|
||||||
{
|
{
|
||||||
var tenant = await repository.GetByIdAsync(tenantId);
|
var tenant = await tenantManager.FindByIdAsync(tenantId);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Tenant with ID {tenantId} not found");
|
throw new KeyNotFoundException($"Tenant with ID {tenantId} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
var roles = await roleRepository.GetPagedAsync(1, int.MaxValue, null, tenantId.ToString());
|
var roles = await context.Roles
|
||||||
|
.Where(r => r.TenantId == tenantId)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
return roles.Select(r => new
|
return roles.Select(r => new
|
||||||
{
|
{
|
||||||
id = r.Id,
|
id = r.Id,
|
||||||
@ -131,7 +141,7 @@ public class TenantService(
|
|||||||
|
|
||||||
public async Task<TenantSettingsDto> GetTenantSettingsAsync(long id)
|
public async Task<TenantSettingsDto> GetTenantSettingsAsync(long id)
|
||||||
{
|
{
|
||||||
var tenant = await repository.GetByIdAsync(id);
|
var tenant = await tenantManager.FindByIdAsync(id);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Tenant with ID {id} not found");
|
throw new KeyNotFoundException($"Tenant with ID {id} not found");
|
||||||
@ -150,39 +160,46 @@ public class TenantService(
|
|||||||
|
|
||||||
public async Task UpdateTenantSettingsAsync(long id, TenantSettingsDto settings)
|
public async Task UpdateTenantSettingsAsync(long id, TenantSettingsDto settings)
|
||||||
{
|
{
|
||||||
var tenant = await repository.GetByIdAsync(id);
|
var tenant = await tenantManager.FindByIdAsync(id);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
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
|
||||||
{
|
{
|
||||||
TenantId = dto.TenantId,
|
TenantCode = dto.TenantCode,
|
||||||
Name = dto.Name,
|
Name = dto.Name,
|
||||||
ContactName = dto.ContactName,
|
ContactName = dto.ContactName,
|
||||||
ContactEmail = dto.ContactEmail,
|
ContactEmail = dto.ContactEmail,
|
||||||
ContactPhone = dto.ContactPhone,
|
ContactPhone = dto.ContactPhone,
|
||||||
MaxUsers = dto.MaxUsers,
|
MaxUsers = dto.MaxUsers,
|
||||||
Description = dto.Description,
|
Description = dto.Description,
|
||||||
Status = dto.Status,
|
|
||||||
ExpiresAt = dto.ExpiresAt,
|
ExpiresAt = dto.ExpiresAt,
|
||||||
|
Status = TenantStatus.Active,
|
||||||
CreatedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
await repository.AddAsync(tenant);
|
var result = await tenantManager.CreateAsync(tenant);
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "create", "Tenant", tenant.Id, tenant.TenantId, null, System.Text.Json.JsonSerializer.Serialize(dto));
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
var errors = string.Join(", ", result.Errors.Select(e => e.Description));
|
||||||
|
throw new InvalidOperationException($"Failed to create tenant: {errors}");
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
@ -198,7 +215,7 @@ public class TenantService(
|
|||||||
|
|
||||||
public async Task<TenantDto> UpdateTenantAsync(long id, UpdateTenantDto dto)
|
public async Task<TenantDto> UpdateTenantAsync(long id, UpdateTenantDto dto)
|
||||||
{
|
{
|
||||||
var tenant = await repository.GetByIdAsync(id);
|
var tenant = await tenantManager.FindByIdAsync(id);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Tenant with ID {id} not found");
|
throw new KeyNotFoundException($"Tenant with ID {id} not found");
|
||||||
@ -210,26 +227,29 @@ public class TenantService(
|
|||||||
tenant.ContactName = dto.ContactName;
|
tenant.ContactName = dto.ContactName;
|
||||||
tenant.ContactEmail = dto.ContactEmail;
|
tenant.ContactEmail = dto.ContactEmail;
|
||||||
tenant.ContactPhone = dto.ContactPhone;
|
tenant.ContactPhone = dto.ContactPhone;
|
||||||
tenant.MaxUsers = dto.MaxUsers;
|
|
||||||
tenant.Description = dto.Description;
|
|
||||||
tenant.Status = dto.Status;
|
|
||||||
tenant.ExpiresAt = dto.ExpiresAt;
|
|
||||||
tenant.UpdatedAt = DateTime.UtcNow;
|
tenant.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
await repository.UpdateAsync(tenant);
|
var result = await tenantManager.UpdateAsync(tenant);
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "update", "Tenant", tenant.Id, tenant.TenantId, oldValue, System.Text.Json.JsonSerializer.Serialize(tenant));
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
var errors = string.Join(", ", result.Errors.Select(e => e.Description));
|
||||||
|
throw new InvalidOperationException($"Failed to update tenant: {errors}");
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
ContactPhone = tenant.ContactPhone,
|
ContactPhone = tenant.ContactPhone,
|
||||||
MaxUsers = tenant.MaxUsers,
|
MaxUsers = tenant.MaxUsers,
|
||||||
UserCount = await repository.GetUserCountAsync(tenant.Id),
|
UserCount = await tenantManager.GetUserCountAsync(tenant.Id),
|
||||||
Status = tenant.Status,
|
Status = tenant.Status,
|
||||||
ExpiresAt = tenant.ExpiresAt,
|
ExpiresAt = tenant.ExpiresAt,
|
||||||
Description = tenant.Description,
|
Description = tenant.Description,
|
||||||
@ -239,7 +259,7 @@ public class TenantService(
|
|||||||
|
|
||||||
public async Task DeleteTenantAsync(long id)
|
public async Task DeleteTenantAsync(long id)
|
||||||
{
|
{
|
||||||
var tenant = await repository.GetByIdAsync(id);
|
var tenant = await tenantManager.FindByIdAsync(id);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Tenant with ID {id} not found");
|
throw new KeyNotFoundException($"Tenant with ID {id} not found");
|
||||||
@ -247,30 +267,39 @@ public class TenantService(
|
|||||||
|
|
||||||
var oldValue = System.Text.Json.JsonSerializer.Serialize(tenant);
|
var oldValue = System.Text.Json.JsonSerializer.Serialize(tenant);
|
||||||
|
|
||||||
var users = await userRepository.GetPagedAsync(1, int.MaxValue, null, null, id.ToString());
|
var users = await context.Users
|
||||||
|
.Where(u => u.TenantInfo.TenantId == id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
user.IsDeleted = true;
|
user.IsDeleted = true;
|
||||||
user.UpdatedTime = DateTime.UtcNow;
|
user.UpdatedTime = DateTime.UtcNow;
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
tenant.IsDeleted = true;
|
tenant.IsDeleted = true;
|
||||||
await repository.UpdateAsync(tenant);
|
var result = await tenantManager.UpdateAsync(tenant);
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "delete", "Tenant", tenant.Id, tenant.TenantId, oldValue);
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
var errors = string.Join(", ", result.Errors.Select(e => e.Description));
|
||||||
|
throw new InvalidOperationException($"Failed to delete tenant: {errors}");
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
var httpContext = httpContextAccessor.HttpContext;
|
var httpContext = httpContextAccessor.HttpContext;
|
||||||
var userName = httpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier) ?? httpContext?.User?.Identity?.Name ?? "system";
|
var userName = httpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier) ?? httpContext?.User?.Identity?.Name ?? "system";
|
||||||
var tenantId = httpContext?.User?.FindFirstValue("TenantId");
|
var tenantIdClaim = httpContext?.User?.FindFirstValue("TenantId");
|
||||||
|
|
||||||
var log = new AuditLog
|
var log = new AuditLog
|
||||||
{
|
{
|
||||||
Operator = userName,
|
Operator = userName,
|
||||||
TenantId = tenantId,
|
TenantId = tenantIdClaim,
|
||||||
Operation = operation,
|
Operation = operation,
|
||||||
Action = action,
|
Action = action,
|
||||||
TargetType = targetType,
|
TargetType = targetType,
|
||||||
|
|||||||
@ -1,15 +1,19 @@
|
|||||||
using Fengling.Console.Models.Dtos;
|
using Fengling.Console.Models.Dtos;
|
||||||
using Fengling.Console.Repositories;
|
using Fengling.Platform.Domain.AggregatesModel.UserAggregate;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.RoleAggregate;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Fengling.Console.Datas;
|
|
||||||
using Fengling.Console.Models.Entities;
|
|
||||||
|
|
||||||
namespace Fengling.Console.Services;
|
namespace Fengling.Console.Services;
|
||||||
|
|
||||||
public interface IUserService
|
public interface IUserService
|
||||||
{
|
{
|
||||||
Task<(IEnumerable<UserDto> Items, int TotalCount)> GetUsersAsync(int page, int pageSize, string? userName = null, string? email = null, string? tenantId = null);
|
Task<(IEnumerable<UserDto> Items, int TotalCount)> GetUsersAsync(int page, int pageSize, string? userName = null,
|
||||||
|
string? email = null, string? tenantCode = null);
|
||||||
|
|
||||||
Task<UserDto?> GetUserAsync(long id);
|
Task<UserDto?> GetUserAsync(long id);
|
||||||
Task<UserDto> CreateUserAsync(CreateUserDto dto);
|
Task<UserDto> CreateUserAsync(CreateUserDto dto);
|
||||||
Task<UserDto> UpdateUserAsync(long id, UpdateUserDto dto);
|
Task<UserDto> UpdateUserAsync(long id, UpdateUserDto dto);
|
||||||
@ -18,32 +22,59 @@ public interface IUserService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class UserService(
|
public class UserService(
|
||||||
IUserRepository repository,
|
ITenantManager tenantManager,
|
||||||
ITenantRepository tenantRepository,
|
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
RoleManager<ApplicationRole> roleManager,
|
RoleManager<ApplicationRole> roleManager,
|
||||||
ApplicationDbContext context,
|
PlatformDbContext context,
|
||||||
IHttpContextAccessor httpContextAccessor)
|
IHttpContextAccessor httpContextAccessor)
|
||||||
: IUserService
|
: IUserService
|
||||||
{
|
{
|
||||||
public async Task<(IEnumerable<UserDto> Items, int TotalCount)> GetUsersAsync(int page, int pageSize, string? userName = null, string? email = null, string? tenantId = null)
|
public async Task<(IEnumerable<UserDto> Items, int TotalCount)> GetUsersAsync(int page, int pageSize,
|
||||||
|
string? userName = null, string? email = null,
|
||||||
|
string? tenantCode = null)
|
||||||
{
|
{
|
||||||
var users = await repository.GetPagedAsync(page, pageSize, userName, email, tenantId);
|
var query = context.Users.AsQueryable();
|
||||||
var totalCount = await repository.CountAsync(userName, email, tenantId);
|
|
||||||
|
if (!string.IsNullOrEmpty(userName))
|
||||||
|
{
|
||||||
|
query = query.Where(u => u.UserName != null && u.UserName.Contains(userName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(email))
|
||||||
|
{
|
||||||
|
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(tenantCode))
|
||||||
|
{
|
||||||
|
query = query.Where(u => u.TenantInfo != null &&
|
||||||
|
u.TenantInfo.TenantCode != null &&
|
||||||
|
u.TenantInfo.TenantCode.Contains(tenantCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalCount = await query.CountAsync();
|
||||||
|
var users = await query
|
||||||
|
.OrderByDescending(u => u.CreatedTime)
|
||||||
|
.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
var userDtos = new List<UserDto>();
|
var userDtos = new List<UserDto>();
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
var roles = await userManager.GetRolesAsync(user);
|
var roles = await userManager.GetRolesAsync(user);
|
||||||
|
var tenant = user.TenantInfo?.TenantId > 0
|
||||||
|
? await tenantManager.FindByIdAsync(user.TenantInfo.TenantId)
|
||||||
|
: null;
|
||||||
userDtos.Add(new UserDto
|
userDtos.Add(new UserDto
|
||||||
{
|
{
|
||||||
Id = user.Id,
|
Id = user.Id,
|
||||||
UserName = user.UserName,
|
UserName = user.UserName,
|
||||||
Email = user.Email,
|
Email = user.Email,
|
||||||
RealName = user.RealName,
|
RealName = user.RealName,
|
||||||
Phone = user.Phone,
|
PhoneNumber = user.PhoneNumber,
|
||||||
TenantId = user.TenantInfo.Id,
|
TenantCode = user.TenantInfo?.TenantCode,
|
||||||
TenantName = user.TenantInfo.Name,
|
TenantName = tenant?.Name ?? "",
|
||||||
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,
|
||||||
@ -56,19 +87,20 @@ public class UserService(
|
|||||||
|
|
||||||
public async Task<UserDto?> GetUserAsync(long id)
|
public async Task<UserDto?> GetUserAsync(long id)
|
||||||
{
|
{
|
||||||
var user = await repository.GetByIdAsync(id);
|
var user = await context.Users.FindAsync(id);
|
||||||
if (user == null) return null;
|
if (user == null) return null;
|
||||||
|
|
||||||
var roles = await userManager.GetRolesAsync(user);
|
var roles = await userManager.GetRolesAsync(user);
|
||||||
|
var tenant = user.TenantInfo?.TenantId > 0 ? await tenantManager.FindByIdAsync(user.TenantInfo.TenantId) : null;
|
||||||
return new UserDto
|
return new UserDto
|
||||||
{
|
{
|
||||||
Id = user.Id,
|
Id = user.Id,
|
||||||
UserName = user.UserName,
|
UserName = user.UserName,
|
||||||
Email = user.Email,
|
Email = user.Email,
|
||||||
RealName = user.RealName,
|
RealName = user.RealName,
|
||||||
Phone = user.Phone,
|
PhoneNumber = user.PhoneNumber,
|
||||||
TenantId = user.TenantInfo.Id,
|
TenantCode = user.TenantInfo?.TenantCode,
|
||||||
TenantName = user.TenantInfo.Name,
|
TenantName = tenant?.Name ?? "",
|
||||||
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,
|
||||||
@ -78,25 +110,28 @@ public class UserService(
|
|||||||
|
|
||||||
public async Task<UserDto> CreateUserAsync(CreateUserDto dto)
|
public async Task<UserDto> CreateUserAsync(CreateUserDto dto)
|
||||||
{
|
{
|
||||||
var tenantId = dto.TenantId ?? 0;
|
|
||||||
Tenant? tenant = null;
|
Tenant? tenant = null;
|
||||||
|
|
||||||
if (tenantId != 0)
|
if (dto.TenantId.HasValue && dto.TenantId.Value > 0)
|
||||||
{
|
{
|
||||||
tenant = await tenantRepository.GetByIdAsync(tenantId);
|
tenant = await tenantManager.FindByIdAsync(dto.TenantId.Value);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid tenant ID");
|
throw new InvalidOperationException("Invalid tenant ID");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tenantInfo = tenant != null
|
||||||
|
? new TenantInfo(tenant.Id, tenant.TenantCode, tenant.Name)
|
||||||
|
: new TenantInfo(0, "", "");
|
||||||
|
|
||||||
var user = new ApplicationUser
|
var user = new ApplicationUser
|
||||||
{
|
{
|
||||||
UserName = dto.UserName,
|
UserName = dto.UserName,
|
||||||
Email = dto.Email,
|
Email = dto.Email,
|
||||||
RealName = dto.RealName,
|
RealName = dto.RealName,
|
||||||
Phone = dto.Phone,
|
PhoneNumber = dto.PhoneNumber,
|
||||||
TenantInfo = new TenantInfo(tenantId, tenant?.TenantId ?? "default", tenant?.Name ?? "默认租户"),
|
TenantInfo = tenantInfo,
|
||||||
EmailConfirmed = dto.EmailConfirmed,
|
EmailConfirmed = dto.EmailConfirmed,
|
||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
@ -107,7 +142,7 @@ public class UserService(
|
|||||||
throw new InvalidOperationException(string.Join(", ", result.Errors.Select(e => e.Description)));
|
throw new InvalidOperationException(string.Join(", ", result.Errors.Select(e => e.Description)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dto.RoleIds != null && dto.RoleIds.Any())
|
if (dto.RoleIds.Count != 0)
|
||||||
{
|
{
|
||||||
foreach (var roleId in dto.RoleIds)
|
foreach (var roleId in dto.RoleIds)
|
||||||
{
|
{
|
||||||
@ -125,7 +160,8 @@ public class UserService(
|
|||||||
await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
await CreateAuditLog("user", "create", "User", user.Id, user.UserName, null, System.Text.Json.JsonSerializer.Serialize(dto));
|
await CreateAuditLog("user", "create", "User", user.Id, user.UserName, null,
|
||||||
|
System.Text.Json.JsonSerializer.Serialize(dto));
|
||||||
|
|
||||||
var roles = await userManager.GetRolesAsync(user);
|
var roles = await userManager.GetRolesAsync(user);
|
||||||
return new UserDto
|
return new UserDto
|
||||||
@ -134,9 +170,9 @@ public class UserService(
|
|||||||
UserName = user.UserName,
|
UserName = user.UserName,
|
||||||
Email = user.Email,
|
Email = user.Email,
|
||||||
RealName = user.RealName,
|
RealName = user.RealName,
|
||||||
Phone = user.Phone,
|
PhoneNumber = user.PhoneNumber,
|
||||||
TenantId = user.TenantInfo.Id,
|
TenantCode = user.TenantInfo.TenantId.ToString(),
|
||||||
TenantName = user.TenantInfo.Name,
|
TenantName = tenant?.Name ?? "",
|
||||||
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,
|
||||||
@ -146,7 +182,7 @@ public class UserService(
|
|||||||
|
|
||||||
public async Task<UserDto> UpdateUserAsync(long id, UpdateUserDto dto)
|
public async Task<UserDto> UpdateUserAsync(long id, UpdateUserDto dto)
|
||||||
{
|
{
|
||||||
var user = await repository.GetByIdAsync(id);
|
var user = await context.Users.FindAsync(id);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"User with ID {id} not found");
|
throw new KeyNotFoundException($"User with ID {id} not found");
|
||||||
@ -156,10 +192,12 @@ public class UserService(
|
|||||||
|
|
||||||
user.Email = dto.Email;
|
user.Email = dto.Email;
|
||||||
user.RealName = dto.RealName;
|
user.RealName = dto.RealName;
|
||||||
user.Phone = dto.Phone;
|
user.PhoneNumber = dto.PhoneNumber;
|
||||||
user.EmailConfirmed = dto.EmailConfirmed;
|
user.EmailConfirmed = dto.EmailConfirmed;
|
||||||
user.UpdatedTime = DateTime.UtcNow;
|
user.UpdatedTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
await userManager.UpdateAsync(user);
|
||||||
|
|
||||||
if (dto.IsActive)
|
if (dto.IsActive)
|
||||||
{
|
{
|
||||||
await userManager.SetLockoutEnabledAsync(user, false);
|
await userManager.SetLockoutEnabledAsync(user, false);
|
||||||
@ -171,9 +209,10 @@ public class UserService(
|
|||||||
await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.SaveChangesAsync();
|
var tenant = user.TenantInfo?.TenantId > 0 ? await tenantManager.FindByIdAsync(user.TenantInfo.TenantId) : null;
|
||||||
|
|
||||||
await CreateAuditLog("user", "update", "User", user.Id, user.UserName, oldValue, System.Text.Json.JsonSerializer.Serialize(user));
|
await CreateAuditLog("user", "update", "User", user.Id, user.UserName, oldValue,
|
||||||
|
System.Text.Json.JsonSerializer.Serialize(user));
|
||||||
|
|
||||||
var roles = await userManager.GetRolesAsync(user);
|
var roles = await userManager.GetRolesAsync(user);
|
||||||
return new UserDto
|
return new UserDto
|
||||||
@ -182,9 +221,9 @@ public class UserService(
|
|||||||
UserName = user.UserName,
|
UserName = user.UserName,
|
||||||
Email = user.Email,
|
Email = user.Email,
|
||||||
RealName = user.RealName,
|
RealName = user.RealName,
|
||||||
Phone = user.Phone,
|
PhoneNumber = user.PhoneNumber,
|
||||||
TenantId = user.TenantInfo.Id,
|
TenantCode = user.TenantInfo?.TenantCode,
|
||||||
TenantName = user.TenantInfo.Name,
|
TenantName = tenant?.Name ?? "",
|
||||||
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,
|
||||||
@ -213,7 +252,7 @@ public class UserService(
|
|||||||
|
|
||||||
public async Task DeleteUserAsync(long id)
|
public async Task DeleteUserAsync(long id)
|
||||||
{
|
{
|
||||||
var user = await repository.GetByIdAsync(id);
|
var user = await context.Users.FindAsync(id);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"User with ID {id} not found");
|
throw new KeyNotFoundException($"User with ID {id} not found");
|
||||||
@ -227,16 +266,18 @@ public class UserService(
|
|||||||
await CreateAuditLog("user", "delete", "User", user.Id, user.UserName, oldValue);
|
await CreateAuditLog("user", "delete", "User", user.Id, user.UserName, 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)
|
||||||
{
|
{
|
||||||
var httpContext = httpContextAccessor.HttpContext;
|
var httpContext = httpContextAccessor.HttpContext;
|
||||||
var userName = httpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier) ?? httpContext?.User?.Identity?.Name ?? "system";
|
var userName = httpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier) ??
|
||||||
var tenantId = httpContext?.User?.FindFirstValue("TenantId");
|
httpContext?.User?.Identity?.Name ?? "system";
|
||||||
|
var tenantIdClaim = httpContext?.User?.FindFirstValue("TenantId");
|
||||||
|
|
||||||
var log = new AuditLog
|
var log = new AuditLog
|
||||||
{
|
{
|
||||||
Operator = userName,
|
Operator = userName,
|
||||||
TenantId = tenantId,
|
TenantId = tenantIdClaim,
|
||||||
Operation = operation,
|
Operation = operation,
|
||||||
Action = action,
|
Action = action,
|
||||||
TargetType = targetType,
|
TargetType = targetType,
|
||||||
|
|||||||
BIN
bin\Debug/net10.0/BuildHost-net472/Microsoft.Build.Locator.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/Microsoft.Build.Locator.dll
Executable file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||||
|
</startup>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Build.Utilities.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Build.Tasks.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.IO.Redist" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
||||||
BIN
bin\Debug/net10.0/BuildHost-net472/Microsoft.IO.Redist.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/Microsoft.IO.Redist.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/Newtonsoft.Json.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/Newtonsoft.Json.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/System.Buffers.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/System.Buffers.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/System.Collections.Immutable.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/System.Collections.Immutable.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/System.CommandLine.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/System.CommandLine.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/System.Memory.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/System.Memory.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/System.Numerics.Vectors.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/System.Numerics.Vectors.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/System.Runtime.CompilerServices.Unsafe.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/System.Runtime.CompilerServices.Unsafe.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/System.Threading.Tasks.Extensions.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/System.Threading.Tasks.Extensions.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/cs/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/cs/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/de/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/de/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/es/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/es/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/fr/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/fr/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/it/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/it/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/ja/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/ja/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/ko/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/ko/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/pl/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/pl/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/pt-BR/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/pt-BR/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/ru/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/ru/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/tr/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/tr/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/zh-Hans/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/zh-Hans/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-net472/zh-Hant/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-net472/zh-Hant/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/Microsoft.Build.Locator.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/Microsoft.Build.Locator.dll
Executable file
Binary file not shown.
@ -0,0 +1,260 @@
|
|||||||
|
{
|
||||||
|
"runtimeTarget": {
|
||||||
|
"name": ".NETCoreApp,Version=v6.0",
|
||||||
|
"signature": ""
|
||||||
|
},
|
||||||
|
"compilationOptions": {},
|
||||||
|
"targets": {
|
||||||
|
".NETCoreApp,Version=v6.0": {
|
||||||
|
"Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost/4.14.0-3.25262.10": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Build.Locator": "1.6.10",
|
||||||
|
"Microsoft.CodeAnalysis.NetAnalyzers": "8.0.0-preview.23468.1",
|
||||||
|
"Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers": "3.3.4-beta1.22504.1",
|
||||||
|
"Microsoft.DotNet.XliffTasks": "9.0.0-beta.25255.5",
|
||||||
|
"Microsoft.VisualStudio.Threading.Analyzers": "17.13.2",
|
||||||
|
"Newtonsoft.Json": "13.0.3",
|
||||||
|
"Roslyn.Diagnostics.Analyzers": "3.11.0-beta1.24081.1",
|
||||||
|
"System.Collections.Immutable": "9.0.0",
|
||||||
|
"System.CommandLine": "2.0.0-beta4.24528.1"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll": {}
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "cs"
|
||||||
|
},
|
||||||
|
"de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "de"
|
||||||
|
},
|
||||||
|
"es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "es"
|
||||||
|
},
|
||||||
|
"fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "fr"
|
||||||
|
},
|
||||||
|
"it/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "it"
|
||||||
|
},
|
||||||
|
"ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "ja"
|
||||||
|
},
|
||||||
|
"ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "ko"
|
||||||
|
},
|
||||||
|
"pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "pl"
|
||||||
|
},
|
||||||
|
"pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "pt-BR"
|
||||||
|
},
|
||||||
|
"ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "ru"
|
||||||
|
},
|
||||||
|
"tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "tr"
|
||||||
|
},
|
||||||
|
"zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "zh-Hans"
|
||||||
|
},
|
||||||
|
"zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": {
|
||||||
|
"locale": "zh-Hant"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Build.Locator/1.6.10": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net6.0/Microsoft.Build.Locator.dll": {
|
||||||
|
"assemblyVersion": "1.0.0.0",
|
||||||
|
"fileVersion": "1.6.10.57384"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.BannedApiAnalyzers/3.11.0-beta1.24081.1": {},
|
||||||
|
"Microsoft.CodeAnalysis.NetAnalyzers/8.0.0-preview.23468.1": {},
|
||||||
|
"Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers/3.3.4-beta1.22504.1": {},
|
||||||
|
"Microsoft.CodeAnalysis.PublicApiAnalyzers/3.11.0-beta1.24081.1": {},
|
||||||
|
"Microsoft.DotNet.XliffTasks/9.0.0-beta.25255.5": {},
|
||||||
|
"Microsoft.VisualStudio.Threading.Analyzers/17.13.2": {},
|
||||||
|
"Newtonsoft.Json/13.0.3": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net6.0/Newtonsoft.Json.dll": {
|
||||||
|
"assemblyVersion": "13.0.0.0",
|
||||||
|
"fileVersion": "13.0.3.27908"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Roslyn.Diagnostics.Analyzers/3.11.0-beta1.24081.1": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.CodeAnalysis.BannedApiAnalyzers": "3.11.0-beta1.24081.1",
|
||||||
|
"Microsoft.CodeAnalysis.PublicApiAnalyzers": "3.11.0-beta1.24081.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Collections.Immutable/9.0.0": {
|
||||||
|
"dependencies": {
|
||||||
|
"System.Memory": "4.5.5",
|
||||||
|
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/netstandard2.0/System.Collections.Immutable.dll": {
|
||||||
|
"assemblyVersion": "9.0.0.0",
|
||||||
|
"fileVersion": "9.0.24.52809"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.CommandLine/2.0.0-beta4.24528.1": {
|
||||||
|
"dependencies": {
|
||||||
|
"System.Memory": "4.5.5"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/netstandard2.0/System.CommandLine.dll": {
|
||||||
|
"assemblyVersion": "2.0.0.0",
|
||||||
|
"fileVersion": "2.0.24.52801"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"lib/netstandard2.0/cs/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "cs"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/de/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "de"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/es/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "es"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/fr/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "fr"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/it/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "it"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/ja/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "ja"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/ko/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "ko"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/pl/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "pl"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/pt-BR/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "pt-BR"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/ru/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "ru"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/tr/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "tr"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/zh-Hans/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "zh-Hans"
|
||||||
|
},
|
||||||
|
"lib/netstandard2.0/zh-Hant/System.CommandLine.resources.dll": {
|
||||||
|
"locale": "zh-Hant"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"System.Memory/4.5.5": {},
|
||||||
|
"System.Runtime.CompilerServices.Unsafe/6.0.0": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost/4.14.0-3.25262.10": {
|
||||||
|
"type": "project",
|
||||||
|
"serviceable": false,
|
||||||
|
"sha512": ""
|
||||||
|
},
|
||||||
|
"Microsoft.Build.Locator/1.6.10": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-DJhCkTGqy1LMJzEmG/2qxRTMHwdPc3WdVoGQI5o5mKHVo4dsHrCMLIyruwU/NSvPNSdvONlaf7jdFXnAMuxAuA==",
|
||||||
|
"path": "microsoft.build.locator/1.6.10",
|
||||||
|
"hashPath": "microsoft.build.locator.1.6.10.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.BannedApiAnalyzers/3.11.0-beta1.24081.1": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-DH6L3rsbjppLrHM2l2/NKbnMaYd0NFHx2pjZaFdrVcRkONrV3i9FHv6Id8Dp6/TmjhXQsJVJJFbhhjkpuP1xxg==",
|
||||||
|
"path": "microsoft.codeanalysis.bannedapianalyzers/3.11.0-beta1.24081.1",
|
||||||
|
"hashPath": "microsoft.codeanalysis.bannedapianalyzers.3.11.0-beta1.24081.1.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.NetAnalyzers/8.0.0-preview.23468.1": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-ZhIvyxmUCqb8OiU/VQfxfuAmIB4lQsjqhMVYKeoyxzSI+d7uR5Pzx3ZKoaIhPizQ15wa4lnyD6wg3TnSJ6P4LA==",
|
||||||
|
"path": "microsoft.codeanalysis.netanalyzers/8.0.0-preview.23468.1",
|
||||||
|
"hashPath": "microsoft.codeanalysis.netanalyzers.8.0.0-preview.23468.1.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers/3.3.4-beta1.22504.1": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-2XRlqPAzVke7Sb80+UqaC7o57OwfK+tIr+aIOxrx41RWDMeR2SBUW7kL4sd6hfLFfBNsLo3W5PT+UwfvwPaOzA==",
|
||||||
|
"path": "microsoft.codeanalysis.performancesensitiveanalyzers/3.3.4-beta1.22504.1",
|
||||||
|
"hashPath": "microsoft.codeanalysis.performancesensitiveanalyzers.3.3.4-beta1.22504.1.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.CodeAnalysis.PublicApiAnalyzers/3.11.0-beta1.24081.1": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-3bYGBihvoNO0rhCOG1U9O50/4Q8suZ+glHqQLIAcKvnodSnSW+dYWYzTNb1UbS8pUS8nAUfxSFMwuMup/G5DtQ==",
|
||||||
|
"path": "microsoft.codeanalysis.publicapianalyzers/3.11.0-beta1.24081.1",
|
||||||
|
"hashPath": "microsoft.codeanalysis.publicapianalyzers.3.11.0-beta1.24081.1.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.DotNet.XliffTasks/9.0.0-beta.25255.5": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-bb0fZB5ViPscdfYeWlmtyXJMzNkgcpkV5RWmXktfV9lwIUZgNZmFotUXrdcTyZzrN7v1tQK/Y6BGnbkP9gEsXg==",
|
||||||
|
"path": "microsoft.dotnet.xlifftasks/9.0.0-beta.25255.5",
|
||||||
|
"hashPath": "microsoft.dotnet.xlifftasks.9.0.0-beta.25255.5.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.VisualStudio.Threading.Analyzers/17.13.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-Qcd8IlaTXZVq3wolBnzby1P7kWihdWaExtD8riumiKuG1sHa8EgjV/o70TMjTaeUMhomBbhfdC9OPwAHoZfnjQ==",
|
||||||
|
"path": "microsoft.visualstudio.threading.analyzers/17.13.2",
|
||||||
|
"hashPath": "microsoft.visualstudio.threading.analyzers.17.13.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Newtonsoft.Json/13.0.3": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
|
||||||
|
"path": "newtonsoft.json/13.0.3",
|
||||||
|
"hashPath": "newtonsoft.json.13.0.3.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Roslyn.Diagnostics.Analyzers/3.11.0-beta1.24081.1": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-reHqZCDKifA+DURcL8jUfYkMGL4FpgNt5LI0uWTS6IpM8kKVbu/kO8byZsqfhBu4wUzT3MBDcoMfzhZPdENIpg==",
|
||||||
|
"path": "roslyn.diagnostics.analyzers/3.11.0-beta1.24081.1",
|
||||||
|
"hashPath": "roslyn.diagnostics.analyzers.3.11.0-beta1.24081.1.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.Collections.Immutable/9.0.0": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w==",
|
||||||
|
"path": "system.collections.immutable/9.0.0",
|
||||||
|
"hashPath": "system.collections.immutable.9.0.0.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.CommandLine/2.0.0-beta4.24528.1": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-Xt8tsSU8yd0ZpbT9gl5DAwkMYWLo8PV1fq2R/belrUbHVVOIKqhLfbWksbdknUDpmzMHZenBtD6AGAp9uJTa2w==",
|
||||||
|
"path": "system.commandline/2.0.0-beta4.24528.1",
|
||||||
|
"hashPath": "system.commandline.2.0.0-beta4.24528.1.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.Memory/4.5.5": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
|
||||||
|
"path": "system.memory/4.5.5",
|
||||||
|
"hashPath": "system.memory.4.5.5.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"System.Runtime.CompilerServices.Unsafe/6.0.0": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
|
||||||
|
"path": "system.runtime.compilerservices.unsafe/6.0.0",
|
||||||
|
"hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@ -0,0 +1,605 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Build.Utilities.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Build.Tasks.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.VisualBasic.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Win32.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Collections.Concurrent" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Collections.NonGeneric" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Collections.Specialized" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Collections" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.ComponentModel.EventBasedAsync" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.ComponentModel.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.ComponentModel.TypeConverter" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.ComponentModel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Data.Common" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Diagnostics.Contracts" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Diagnostics.FileVersionInfo" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Diagnostics.Process" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Diagnostics.TextWriterTraceListener" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Diagnostics.TraceSource" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Diagnostics.Tracing" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Drawing.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.Compression.ZipFile" publicKeyToken="b77a5c561934e089" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.FileSystem.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.FileSystem.DriveInfo" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.FileSystem.Watcher" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.IsolatedStorage" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.MemoryMappedFiles" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.Pipes.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.IO.Pipes" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Linq.Expressions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Linq.Parallel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Linq.Queryable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Linq" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.HttpListener" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.Mail" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.NameResolution" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.NetworkInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.Ping" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.Requests" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.Security" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.ServicePoint" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.Sockets" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.WebClient" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.WebHeaderCollection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.WebProxy" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.WebSockets.Client" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Net.WebSockets" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.ObjectModel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Reflection.Emit.ILGeneration" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Reflection.Emit.Lightweight" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Reflection.Emit" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Reflection.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Resources.Writer" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.CompilerServices.VisualC" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.Numerics" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.Serialization.Formatters" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.Serialization.Json" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.Serialization.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.Serialization.Xml" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Claims" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Cryptography.Algorithms" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Cryptography.Cng" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Cryptography.Csp" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Cryptography.Encoding" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Cryptography.X509Certificates" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Principal.Windows" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Text.Encoding.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Text.RegularExpressions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Threading.Overlapped" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Threading.Tasks.Parallel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Threading.Thread" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Threading.ThreadPool" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Threading" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Transactions.Local" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Web.HttpUtility" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Xml.ReaderWriter" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Xml.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Xml.XPath" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Xml.XmlSerializer" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="netstandard" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Configuration.ConfigurationManager" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Security.Cryptography.Xml" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.CodeDom" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"runtimeOptions": {
|
||||||
|
"tfm": "net6.0",
|
||||||
|
"framework": {
|
||||||
|
"name": "Microsoft.NETCore.App",
|
||||||
|
"version": "6.0.0"
|
||||||
|
},
|
||||||
|
"rollForward": "Major",
|
||||||
|
"configProperties": {
|
||||||
|
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
bin\Debug/net10.0/BuildHost-netcore/Newtonsoft.Json.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/Newtonsoft.Json.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/System.Collections.Immutable.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/System.Collections.Immutable.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/System.CommandLine.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/System.CommandLine.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/cs/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/cs/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/de/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/de/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/es/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/es/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/fr/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/fr/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/it/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/it/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/ja/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/ja/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/ko/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/ko/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/pl/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/pl/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/pt-BR/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/pt-BR/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/ru/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/ru/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/tr/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/tr/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/zh-Hans/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/zh-Hans/System.CommandLine.resources.dll
Executable file
Binary file not shown.
BIN
bin\Debug/net10.0/BuildHost-netcore/zh-Hant/System.CommandLine.resources.dll
Executable file
BIN
bin\Debug/net10.0/BuildHost-netcore/zh-Hant/System.CommandLine.resources.dll
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user