feat(auth): extract Tenant to Platform domain
- Add Fengling.Platform domain and infrastructure projects - Move Tenant aggregate from AuthService/Console to Platform.Domain - Add TenantRepository and SeedData to Platform - Remove duplicate Tenant/TenantInfo models from AuthService and Console - Update controllers and services to use Platform.Domain.Tenant - Add new migrations for PlatformDbContext BREAKING CHANGE: Tenant entity now uses strongly-typed ID (TenantId)
This commit is contained in:
parent
8184f77c0f
commit
39cc9a8538
@ -1,6 +1,8 @@
|
|||||||
using Fengling.AuthService.Data;
|
using Fengling.AuthService.Data;
|
||||||
using Fengling.AuthService.Models;
|
using Fengling.AuthService.Models;
|
||||||
using Fengling.AuthService.ViewModels;
|
using Fengling.AuthService.ViewModels;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
@ -10,25 +12,14 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
namespace Fengling.AuthService.Controllers;
|
namespace Fengling.AuthService.Controllers;
|
||||||
|
|
||||||
[Route("account")]
|
[Route("account")]
|
||||||
public class AccountController : Controller
|
public class AccountController(
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly ApplicationDbContext _dbContext;
|
|
||||||
private readonly ILogger<AccountController> _logger;
|
|
||||||
|
|
||||||
public AccountController(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
SignInManager<ApplicationUser> signInManager,
|
SignInManager<ApplicationUser> signInManager,
|
||||||
ApplicationDbContext dbContext,
|
ApplicationDbContext dbContext,
|
||||||
ILogger<AccountController> logger)
|
ILogger<AccountController> logger,
|
||||||
|
PlatformDbContext platformDbContext)
|
||||||
|
: Controller
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_dbContext = dbContext;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("login")]
|
[HttpGet("login")]
|
||||||
public IActionResult Login(string returnUrl = "/")
|
public IActionResult Login(string returnUrl = "/")
|
||||||
{
|
{
|
||||||
@ -44,14 +35,14 @@ public class AccountController : Controller
|
|||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = await _userManager.FindByNameAsync(model.Username);
|
var user = await userManager.FindByNameAsync(model.Username);
|
||||||
if (user == null || user.IsDeleted)
|
if (user == null || user.IsDeleted)
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(string.Empty, "用户名或密码错误");
|
ModelState.AddModelError(string.Empty, "用户名或密码错误");
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await _signInManager.PasswordSignInAsync(user, model.Password, model.RememberMe, true);
|
var result = await signInManager.PasswordSignInAsync(user, model.Password, model.RememberMe, true);
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
if (result.IsLockedOut)
|
if (result.IsLockedOut)
|
||||||
@ -83,12 +74,12 @@ public class AccountController : Controller
|
|||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultTenant = await _dbContext.Tenants
|
var tenant = await platformDbContext.Tenants
|
||||||
.FirstOrDefaultAsync(t => t.TenantId == "default");
|
.FirstOrDefaultAsync(t => t.TenantCode == model.TenantCode);
|
||||||
|
|
||||||
if (defaultTenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(string.Empty, "系统配置错误:未找到默认租户");
|
ModelState.AddModelError(string.Empty, $"系统配置错误:未找到租户{model.TenantCode}");
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,10 +89,10 @@ public class AccountController : Controller
|
|||||||
Email = model.Email,
|
Email = model.Email,
|
||||||
NormalizedUserName = model.Username.ToUpper(),
|
NormalizedUserName = model.Username.ToUpper(),
|
||||||
NormalizedEmail = model.Email.ToUpper(),
|
NormalizedEmail = model.Email.ToUpper(),
|
||||||
TenantInfo = new TenantInfo(defaultTenant.Id, defaultTenant.TenantId, defaultTenant.Name)
|
TenantInfo = new TenantInfo(tenant)
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _userManager.CreateAsync(user, model.Password);
|
var result = await userManager.CreateAsync(user, model.Password);
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
foreach (var error in result.Errors)
|
foreach (var error in result.Errors)
|
||||||
@ -111,7 +102,7 @@ public class AccountController : Controller
|
|||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
await signInManager.SignInAsync(user, isPersistent: false);
|
||||||
return LocalRedirect(model.ReturnUrl);
|
return LocalRedirect(model.ReturnUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +118,7 @@ public class AccountController : Controller
|
|||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task<IActionResult> LogoutPost()
|
public async Task<IActionResult> LogoutPost()
|
||||||
{
|
{
|
||||||
await _signInManager.SignOutAsync();
|
await signInManager.SignOutAsync();
|
||||||
return Redirect("/");
|
return Redirect("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Fengling.AuthService.Data;
|
using Fengling.AuthService.Data;
|
||||||
using Fengling.AuthService.Models;
|
using Fengling.AuthService.Models;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -10,21 +11,13 @@ namespace Fengling.AuthService.Controllers;
|
|||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class StatsController : ControllerBase
|
public class StatsController(
|
||||||
{
|
|
||||||
private readonly ApplicationDbContext _context;
|
|
||||||
private readonly IOpenIddictApplicationManager _applicationManager;
|
|
||||||
private readonly ILogger<StatsController> _logger;
|
|
||||||
|
|
||||||
public StatsController(
|
|
||||||
ApplicationDbContext context,
|
ApplicationDbContext context,
|
||||||
IOpenIddictApplicationManager applicationManager,
|
IOpenIddictApplicationManager applicationManager,
|
||||||
ILogger<StatsController> logger)
|
ILogger<StatsController> logger,
|
||||||
|
PlatformDbContext platformDbContext)
|
||||||
|
: ControllerBase
|
||||||
{
|
{
|
||||||
_context = context;
|
|
||||||
_applicationManager = applicationManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("dashboard")]
|
[HttpGet("dashboard")]
|
||||||
public async Task<ActionResult<object>> GetDashboardStats()
|
public async Task<ActionResult<object>> GetDashboardStats()
|
||||||
@ -32,10 +25,10 @@ public class StatsController : ControllerBase
|
|||||||
var today = DateTime.UtcNow.Date;
|
var today = DateTime.UtcNow.Date;
|
||||||
var tomorrow = today.AddDays(1);
|
var tomorrow = today.AddDays(1);
|
||||||
|
|
||||||
var userCount = await _context.Users.CountAsync(u => !u.IsDeleted);
|
var userCount = await context.Users.CountAsync(u => !u.IsDeleted);
|
||||||
var tenantCount = await _context.Tenants.CountAsync(t => !t.IsDeleted);
|
var tenantCount = await platformDbContext.Tenants.CountAsync(t => !t.Deleted);
|
||||||
var oauthClientCount = await CountOAuthClientsAsync();
|
var oauthClientCount = await CountOAuthClientsAsync();
|
||||||
var todayAccessCount = await _context.AccessLogs
|
var todayAccessCount = await context.AccessLogs
|
||||||
.CountAsync(l => l.CreatedAt >= today && l.CreatedAt < tomorrow);
|
.CountAsync(l => l.CreatedAt >= today && l.CreatedAt < tomorrow);
|
||||||
|
|
||||||
return Ok(new
|
return Ok(new
|
||||||
@ -50,7 +43,7 @@ public class StatsController : ControllerBase
|
|||||||
private async Task<int> CountOAuthClientsAsync()
|
private async Task<int> CountOAuthClientsAsync()
|
||||||
{
|
{
|
||||||
var count = 0;
|
var count = 0;
|
||||||
var applications = _applicationManager.ListAsync();
|
var applications = applicationManager.ListAsync();
|
||||||
await foreach (var _ in applications)
|
await foreach (var _ in applications)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
|
|||||||
@ -6,49 +6,42 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
|
|
||||||
namespace Fengling.AuthService.Controllers;
|
namespace Fengling.AuthService.Controllers;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class TenantsController : ControllerBase
|
public class TenantsController(
|
||||||
{
|
|
||||||
private readonly ApplicationDbContext _context;
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly ILogger<TenantsController> _logger;
|
|
||||||
|
|
||||||
public TenantsController(
|
|
||||||
ApplicationDbContext context,
|
ApplicationDbContext context,
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
ILogger<TenantsController> logger)
|
ILogger<TenantsController> logger,
|
||||||
|
PlatformDbContext platformDbContext)
|
||||||
|
: ControllerBase
|
||||||
{
|
{
|
||||||
_context = context;
|
|
||||||
_userManager = userManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<ActionResult<object>> GetTenants(
|
public async Task<ActionResult<object>> GetTenants(
|
||||||
[FromQuery] int page = 1,
|
[FromQuery] int page = 1,
|
||||||
[FromQuery] int pageSize = 10,
|
[FromQuery] int pageSize = 10,
|
||||||
[FromQuery] string? name = null,
|
[FromQuery] string? name = null,
|
||||||
[FromQuery] string? tenantId = null,
|
[FromQuery] string? tenantCode = null,
|
||||||
[FromQuery] string? status = null)
|
[FromQuery] TenantStatus? status = null)
|
||||||
{
|
{
|
||||||
var query = _context.Tenants.AsQueryable();
|
var query = platformDbContext.Tenants.AsQueryable();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(name))
|
if (!string.IsNullOrEmpty(name))
|
||||||
{
|
{
|
||||||
query = query.Where(t => t.Name.Contains(name));
|
query = query.Where(t => t.Name.Contains(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
if (!string.IsNullOrEmpty(tenantCode))
|
||||||
{
|
{
|
||||||
query = query.Where(t => t.TenantId.Contains(tenantId));
|
query = query.Where(t => t.TenantCode.Contains(tenantCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(status))
|
if (status.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(t => t.Status == status);
|
query = query.Where(t => t.Status == status);
|
||||||
}
|
}
|
||||||
@ -64,11 +57,11 @@ public class TenantsController : ControllerBase
|
|||||||
|
|
||||||
foreach (var tenant in tenants)
|
foreach (var tenant in tenants)
|
||||||
{
|
{
|
||||||
var userCount = await _context.Users.CountAsync(u => u.TenantInfo.Id == tenant.Id && !u.IsDeleted);
|
var userCount = await context.Users.CountAsync(u => u.TenantInfo.TenantId == tenant.Id && !u.IsDeleted);
|
||||||
result.Add(new
|
result.Add(new
|
||||||
{
|
{
|
||||||
id = tenant.Id,
|
id = tenant.Id,
|
||||||
tenantId = tenant.TenantId,
|
tenantId = tenant.Id,
|
||||||
name = tenant.Name,
|
name = tenant.Name,
|
||||||
contactName = tenant.ContactName,
|
contactName = tenant.ContactName,
|
||||||
contactEmail = tenant.ContactEmail,
|
contactEmail = tenant.ContactEmail,
|
||||||
@ -92,9 +85,9 @@ public class TenantsController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public async Task<ActionResult<Tenant>> GetTenant(long id)
|
public async Task<ActionResult<Tenant>> GetTenant(TenantId id)
|
||||||
{
|
{
|
||||||
var tenant = await _context.Tenants.FindAsync(id);
|
var tenant = await platformDbContext.Tenants.FindAsync(id);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
@ -103,7 +96,7 @@ public class TenantsController : ControllerBase
|
|||||||
return Ok(new
|
return Ok(new
|
||||||
{
|
{
|
||||||
id = tenant.Id,
|
id = tenant.Id,
|
||||||
tenantId = tenant.TenantId,
|
tenantId = tenant.Id,
|
||||||
name = tenant.Name,
|
name = tenant.Name,
|
||||||
contactName = tenant.ContactName,
|
contactName = tenant.ContactName,
|
||||||
contactEmail = tenant.ContactEmail,
|
contactEmail = tenant.ContactEmail,
|
||||||
@ -118,16 +111,19 @@ public class TenantsController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{tenantId}/users")]
|
[HttpGet("{tenantId}/users")]
|
||||||
public async Task<ActionResult<List<object>>> GetTenantUsers(string tenantId)
|
public async Task<ActionResult<List<object>>> GetTenantUsers(TenantId tenantId)
|
||||||
{
|
{
|
||||||
var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
|
var tenant = await platformDbContext.Tenants
|
||||||
|
.FirstOrDefaultAsync(t => t.Id == tenantId);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var users = await _context.Users
|
var users = await context.Users
|
||||||
.Where(u => u.TenantInfo.Id == tenant.Id && !u.IsDeleted)
|
.Where(u =>
|
||||||
|
u.TenantInfo.TenantId == tenant.Id
|
||||||
|
&& !u.IsDeleted)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var result = users.Select(async u => new
|
var result = users.Select(async u => new
|
||||||
@ -136,8 +132,8 @@ public class TenantsController : ControllerBase
|
|||||||
userName = u.UserName,
|
userName = u.UserName,
|
||||||
email = u.Email,
|
email = u.Email,
|
||||||
realName = u.RealName,
|
realName = u.RealName,
|
||||||
tenantId = u.TenantInfo.Id,
|
tenantId = u.TenantInfo.TenantId,
|
||||||
roles = await _userManager.GetRolesAsync(u),
|
roles = await userManager.GetRolesAsync(u),
|
||||||
isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow,
|
isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow,
|
||||||
createdAt = u.CreatedTime,
|
createdAt = u.CreatedTime,
|
||||||
});
|
});
|
||||||
@ -146,15 +142,16 @@ public class TenantsController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{tenantId}/roles")]
|
[HttpGet("{tenantId}/roles")]
|
||||||
public async Task<ActionResult<List<object>>> GetTenantRoles(string tenantId)
|
public async Task<ActionResult<List<object>>> GetTenantRoles(TenantId tenantId)
|
||||||
{
|
{
|
||||||
var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
|
var tenant = await platformDbContext.Tenants
|
||||||
|
.FirstOrDefaultAsync(t => t.Id == tenantId);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var roles = await _context.Roles
|
var roles = await context.Roles
|
||||||
.Where(r => r.TenantId == tenant.Id)
|
.Where(r => r.TenantId == tenant.Id)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@ -169,9 +166,10 @@ public class TenantsController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{tenantId}/settings")]
|
[HttpGet("{tenantId}/settings")]
|
||||||
public async Task<ActionResult<TenantSettings>> GetTenantSettings(string tenantId)
|
public async Task<ActionResult<TenantSettings>> GetTenantSettings(TenantId tenantId)
|
||||||
{
|
{
|
||||||
var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
|
var tenant = await platformDbContext.Tenants
|
||||||
|
.FirstOrDefaultAsync(t => t.Id == tenantId);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
@ -191,15 +189,16 @@ public class TenantsController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("{tenantId}/settings")]
|
[HttpPut("{tenantId}/settings")]
|
||||||
public async Task<IActionResult> UpdateTenantSettings(string tenantId, TenantSettings settings)
|
public async Task<IActionResult> UpdateTenantSettings(TenantId tenantId, TenantSettings settings)
|
||||||
{
|
{
|
||||||
var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.TenantId == tenantId);
|
var tenant = await platformDbContext.Tenants.FirstOrDefaultAsync(t => t.Id == tenantId);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "update", "TenantSettings", tenant.Id, tenant.TenantId, null, JsonSerializer.Serialize(settings));
|
await CreateAuditLog("tenant", "update", "TenantSettings", tenant.Id, tenant.Name, null,
|
||||||
|
JsonSerializer.Serialize(settings));
|
||||||
|
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
@ -207,24 +206,14 @@ public class TenantsController : ControllerBase
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<Tenant>> CreateTenant(CreateTenantDto dto)
|
public async Task<ActionResult<Tenant>> CreateTenant(CreateTenantDto dto)
|
||||||
{
|
{
|
||||||
var tenant = new Tenant
|
var tenant = new Tenant(dto.TenantCode, dto.TenantName, dto.ContactName, dto.ContactEmail, dto.ContactPhone,
|
||||||
{
|
dto.MaxUsers, dto.Description, dto.ExpiresAt);
|
||||||
TenantId = dto.TenantId,
|
|
||||||
Name = dto.Name,
|
|
||||||
ContactName = dto.ContactName,
|
|
||||||
ContactEmail = dto.ContactEmail,
|
|
||||||
ContactPhone = dto.ContactPhone,
|
|
||||||
MaxUsers = dto.MaxUsers,
|
|
||||||
Description = dto.Description,
|
|
||||||
Status = dto.Status,
|
|
||||||
ExpiresAt = dto.ExpiresAt,
|
|
||||||
CreatedAt = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
_context.Tenants.Add(tenant);
|
platformDbContext.Tenants.Add(tenant);
|
||||||
await _context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "create", "Tenant", tenant.Id, tenant.TenantId, null, JsonSerializer.Serialize(dto));
|
await CreateAuditLog("tenant", "create", "Tenant", tenant.Id, tenant.TenantCode,
|
||||||
|
null, JsonSerializer.Serialize(dto));
|
||||||
|
|
||||||
return CreatedAtAction(nameof(GetTenant), new { id = tenant.Id }, tenant);
|
return CreatedAtAction(nameof(GetTenant), new { id = tenant.Id }, tenant);
|
||||||
}
|
}
|
||||||
@ -232,27 +221,20 @@ public class TenantsController : ControllerBase
|
|||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
public async Task<IActionResult> UpdateTenant(long id, UpdateTenantDto dto)
|
public async Task<IActionResult> UpdateTenant(long id, UpdateTenantDto dto)
|
||||||
{
|
{
|
||||||
var tenant = await _context.Tenants.FindAsync(id);
|
var tenant = await platformDbContext.Tenants.FindAsync(id);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldValue = JsonSerializer.Serialize(tenant);
|
var oldValue = JsonSerializer.Serialize(tenant);
|
||||||
|
tenant.UpdateInfo(dto.Name, dto.ContactName, dto.ContactEmail, dto.ContactPhone);
|
||||||
|
|
||||||
tenant.Name = dto.Name;
|
|
||||||
tenant.ContactName = dto.ContactName;
|
|
||||||
tenant.ContactEmail = dto.ContactEmail;
|
|
||||||
tenant.ContactPhone = dto.ContactPhone;
|
|
||||||
tenant.MaxUsers = dto.MaxUsers;
|
|
||||||
tenant.Description = dto.Description;
|
|
||||||
tenant.Status = dto.Status;
|
|
||||||
tenant.ExpiresAt = dto.ExpiresAt;
|
|
||||||
tenant.UpdatedAt = DateTime.UtcNow;
|
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "update", "Tenant", tenant.Id, tenant.TenantId, oldValue, JsonSerializer.Serialize(tenant));
|
await CreateAuditLog("tenant", "update", "Tenant", tenant.Id, tenant.Name, oldValue,
|
||||||
|
JsonSerializer.Serialize(tenant));
|
||||||
|
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
@ -260,7 +242,7 @@ public class TenantsController : ControllerBase
|
|||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
public async Task<IActionResult> DeleteTenant(long id)
|
public async Task<IActionResult> DeleteTenant(long id)
|
||||||
{
|
{
|
||||||
var tenant = await _context.Tenants.FindAsync(id);
|
var tenant = await platformDbContext.Tenants.FindAsync(id);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
@ -268,22 +250,23 @@ public class TenantsController : ControllerBase
|
|||||||
|
|
||||||
var oldValue = JsonSerializer.Serialize(tenant);
|
var oldValue = JsonSerializer.Serialize(tenant);
|
||||||
|
|
||||||
var users = await _context.Users.Where(u => u.TenantInfo.Id == tenant.Id).ToListAsync();
|
var users = await context.Users.Where(u => u.TenantInfo.TenantId == tenant.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
tenant.IsDeleted = true;
|
tenant.Delete();
|
||||||
await _context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
await CreateAuditLog("tenant", "delete", "Tenant", tenant.Id, tenant.TenantId, oldValue);
|
await CreateAuditLog("tenant", "delete", "Tenant", tenant.Id, tenant.Name, oldValue);
|
||||||
|
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 userName = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.Identity?.Name ?? "system";
|
var userName = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.Identity?.Name ?? "system";
|
||||||
var tenantId = User.FindFirstValue("TenantId");
|
var tenantId = User.FindFirstValue("TenantId");
|
||||||
@ -303,23 +286,21 @@ public class TenantsController : ControllerBase
|
|||||||
NewValue = newValue,
|
NewValue = newValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
_context.AuditLogs.Add(log);
|
context.AuditLogs.Add(log);
|
||||||
await _context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CreateTenantDto
|
public record CreateTenantDto(
|
||||||
{
|
string TenantCode,
|
||||||
public string TenantId { get; set; } = string.Empty;
|
string TenantName,
|
||||||
public string Name { get; set; } = string.Empty;
|
string ContactName,
|
||||||
public string ContactName { get; set; } = string.Empty;
|
string ContactEmail,
|
||||||
public string ContactEmail { get; set; } = string.Empty;
|
string ContactPhone,
|
||||||
public string? ContactPhone { get; set; }
|
int? MaxUsers,
|
||||||
public int? MaxUsers { get; set; }
|
string? Description,
|
||||||
public string? Description { get; set; }
|
string Status,
|
||||||
public string Status { get; set; } = "active";
|
DateTime? ExpiresAt);
|
||||||
public DateTime? ExpiresAt { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdateTenantDto
|
public class UpdateTenantDto
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5,30 +5,22 @@ using Microsoft.AspNetCore.Identity;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
|
|
||||||
namespace Fengling.AuthService.Controllers;
|
namespace Fengling.AuthService.Controllers;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class UsersController : ControllerBase
|
public class UsersController(
|
||||||
{
|
|
||||||
private readonly ApplicationDbContext _context;
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly RoleManager<ApplicationRole> _roleManager;
|
|
||||||
private readonly ILogger<UsersController> _logger;
|
|
||||||
|
|
||||||
public UsersController(
|
|
||||||
ApplicationDbContext context,
|
ApplicationDbContext context,
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
RoleManager<ApplicationRole> roleManager,
|
RoleManager<ApplicationRole> roleManager,
|
||||||
ILogger<UsersController> logger)
|
ILogger<UsersController> logger,
|
||||||
|
PlatformDbContext platformDbContext)
|
||||||
|
: ControllerBase
|
||||||
{
|
{
|
||||||
_context = context;
|
|
||||||
_userManager = userManager;
|
|
||||||
_roleManager = roleManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<ActionResult<object>> GetUsers(
|
public async Task<ActionResult<object>> GetUsers(
|
||||||
@ -36,9 +28,9 @@ public class UsersController : ControllerBase
|
|||||||
[FromQuery] int pageSize = 10,
|
[FromQuery] int pageSize = 10,
|
||||||
[FromQuery] string? userName = null,
|
[FromQuery] string? userName = null,
|
||||||
[FromQuery] string? email = null,
|
[FromQuery] string? email = null,
|
||||||
[FromQuery] string? tenantId = null)
|
[FromQuery] string? tenantCode = null)
|
||||||
{
|
{
|
||||||
var query = _context.Users.AsQueryable();
|
var query = context.Users.AsQueryable();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(userName))
|
if (!string.IsNullOrEmpty(userName))
|
||||||
{
|
{
|
||||||
@ -50,9 +42,9 @@ public class UsersController : ControllerBase
|
|||||||
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
query = query.Where(u => u.Email != null && u.Email.Contains(email));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tenantId))
|
if (!string.IsNullOrEmpty(tenantCode))
|
||||||
{
|
{
|
||||||
query = query.Where(u => u.TenantInfo.Id.ToString() == tenantId);
|
query = query.Where(u => u.TenantInfo.TenantCode == tenantCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalCount = await query.CountAsync();
|
var totalCount = await query.CountAsync();
|
||||||
@ -69,8 +61,8 @@ public class UsersController : ControllerBase
|
|||||||
email = u.Email,
|
email = u.Email,
|
||||||
realName = u.RealName,
|
realName = u.RealName,
|
||||||
phone = u.Phone,
|
phone = u.Phone,
|
||||||
tenantId = u.TenantInfo.Id,
|
tenantId = u.TenantInfo.TenantId,
|
||||||
roles = (await _userManager.GetRolesAsync(u)).ToList(),
|
roles = (await userManager.GetRolesAsync(u)).ToList(),
|
||||||
emailConfirmed = u.EmailConfirmed,
|
emailConfirmed = u.EmailConfirmed,
|
||||||
isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow,
|
isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow,
|
||||||
createdAt = u.CreatedTime,
|
createdAt = u.CreatedTime,
|
||||||
@ -88,13 +80,13 @@ public class UsersController : ControllerBase
|
|||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public async Task<ActionResult<object>> GetUser(long id)
|
public async Task<ActionResult<object>> GetUser(long id)
|
||||||
{
|
{
|
||||||
var user = await _context.Users.FindAsync(id);
|
var user = await context.Users.FindAsync(id);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var roles = await _userManager.GetRolesAsync(user);
|
var roles = await userManager.GetRolesAsync(user);
|
||||||
|
|
||||||
return Ok(new
|
return Ok(new
|
||||||
{
|
{
|
||||||
@ -103,7 +95,7 @@ public class UsersController : ControllerBase
|
|||||||
email = user.Email,
|
email = user.Email,
|
||||||
realName = user.RealName,
|
realName = user.RealName,
|
||||||
phone = user.Phone,
|
phone = user.Phone,
|
||||||
tenantId = user.TenantInfo.Id,
|
tenantId = user.TenantInfo.TenantId,
|
||||||
roles,
|
roles,
|
||||||
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,
|
||||||
@ -115,11 +107,11 @@ public class UsersController : ControllerBase
|
|||||||
public async Task<ActionResult<ApplicationUser>> CreateUser(CreateUserDto dto)
|
public async Task<ActionResult<ApplicationUser>> CreateUser(CreateUserDto dto)
|
||||||
{
|
{
|
||||||
var tenantId = dto.TenantId ?? 0;
|
var tenantId = dto.TenantId ?? 0;
|
||||||
Tenant tenant = null;
|
Tenant? tenant = null;
|
||||||
|
|
||||||
if (tenantId != 0)
|
if (tenantId != 0)
|
||||||
{
|
{
|
||||||
tenant = await _context.Tenants.FindAsync(tenantId);
|
tenant = await platformDbContext.Tenants.FindAsync(tenantId);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
{
|
{
|
||||||
return BadRequest("Invalid tenant ID");
|
return BadRequest("Invalid tenant ID");
|
||||||
@ -132,33 +124,33 @@ public class UsersController : ControllerBase
|
|||||||
Email = dto.Email,
|
Email = dto.Email,
|
||||||
RealName = dto.RealName,
|
RealName = dto.RealName,
|
||||||
Phone = dto.Phone,
|
Phone = dto.Phone,
|
||||||
TenantInfo = new TenantInfo(tenantId, tenant?.TenantId ?? "default", tenant?.Name ?? "默认租户"),
|
TenantInfo = new TenantInfo(tenant!),
|
||||||
EmailConfirmed = dto.EmailConfirmed,
|
EmailConfirmed = dto.EmailConfirmed,
|
||||||
CreatedTime = DateTime.UtcNow,
|
CreatedTime = DateTime.UtcNow,
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _userManager.CreateAsync(user, dto.Password);
|
var result = await userManager.CreateAsync(user, dto.Password);
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
return BadRequest(result.Errors);
|
return BadRequest(result.Errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dto.RoleIds != null && dto.RoleIds.Any())
|
if (dto.RoleIds.Any())
|
||||||
{
|
{
|
||||||
foreach (var roleId in dto.RoleIds)
|
foreach (var roleId in dto.RoleIds)
|
||||||
{
|
{
|
||||||
var role = await _roleManager.FindByIdAsync(roleId.ToString());
|
var role = await roleManager.FindByIdAsync(roleId.ToString());
|
||||||
if (role != null)
|
if (role != null)
|
||||||
{
|
{
|
||||||
await _userManager.AddToRoleAsync(user, role.Name!);
|
await userManager.AddToRoleAsync(user, role.Name!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dto.IsActive)
|
if (!dto.IsActive)
|
||||||
{
|
{
|
||||||
await _userManager.SetLockoutEnabledAsync(user, true);
|
await userManager.SetLockoutEnabledAsync(user, true);
|
||||||
await _userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
await CreateAuditLog("user", "create", "User", user.Id, user.UserName, null, SerializeToJson(dto));
|
await CreateAuditLog("user", "create", "User", user.Id, user.UserName, null, SerializeToJson(dto));
|
||||||
@ -169,7 +161,7 @@ public class UsersController : ControllerBase
|
|||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
public async Task<IActionResult> UpdateUser(long id, UpdateUserDto dto)
|
public async Task<IActionResult> UpdateUser(long id, UpdateUserDto dto)
|
||||||
{
|
{
|
||||||
var user = await _context.Users.FindAsync(id);
|
var user = await context.Users.FindAsync(id);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
@ -185,16 +177,16 @@ public class UsersController : ControllerBase
|
|||||||
|
|
||||||
if (dto.IsActive)
|
if (dto.IsActive)
|
||||||
{
|
{
|
||||||
await _userManager.SetLockoutEnabledAsync(user, false);
|
await userManager.SetLockoutEnabledAsync(user, false);
|
||||||
await _userManager.SetLockoutEndDateAsync(user, null);
|
await userManager.SetLockoutEndDateAsync(user, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _userManager.SetLockoutEnabledAsync(user, true);
|
await userManager.SetLockoutEnabledAsync(user, true);
|
||||||
await _userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
@ -204,14 +196,14 @@ public class UsersController : ControllerBase
|
|||||||
[HttpPut("{id}/password")]
|
[HttpPut("{id}/password")]
|
||||||
public async Task<IActionResult> ResetPassword(long id, ResetPasswordDto dto)
|
public async Task<IActionResult> ResetPassword(long id, ResetPasswordDto dto)
|
||||||
{
|
{
|
||||||
var user = await _userManager.FindByIdAsync(id.ToString());
|
var user = await userManager.FindByIdAsync(id.ToString());
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var token = await _userManager.GeneratePasswordResetTokenAsync(user);
|
var token = await userManager.GeneratePasswordResetTokenAsync(user);
|
||||||
var result = await _userManager.ResetPasswordAsync(user, token, dto.NewPassword);
|
var result = await userManager.ResetPasswordAsync(user, token, dto.NewPassword);
|
||||||
|
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
@ -226,7 +218,7 @@ public class UsersController : ControllerBase
|
|||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
public async Task<IActionResult> DeleteUser(long id)
|
public async Task<IActionResult> DeleteUser(long id)
|
||||||
{
|
{
|
||||||
var user = await _context.Users.FindAsync(id);
|
var user = await context.Users.FindAsync(id);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
@ -235,7 +227,7 @@ public class UsersController : ControllerBase
|
|||||||
var oldValue = System.Text.Json.JsonSerializer.Serialize(user);
|
var oldValue = System.Text.Json.JsonSerializer.Serialize(user);
|
||||||
user.IsDeleted = true;
|
user.IsDeleted = true;
|
||||||
user.UpdatedTime = DateTime.UtcNow;
|
user.UpdatedTime = DateTime.UtcNow;
|
||||||
await _context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
await CreateAuditLog("user", "delete", "User", user.Id, user.UserName, oldValue);
|
await CreateAuditLog("user", "delete", "User", user.Id, user.UserName, oldValue);
|
||||||
|
|
||||||
@ -262,8 +254,8 @@ public class UsersController : ControllerBase
|
|||||||
NewValue = newValue,
|
NewValue = newValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
_context.AuditLogs.Add(log);
|
context.AuditLogs.Add(log);
|
||||||
await _context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string SerializeToJson(object obj)
|
private string SerializeToJson(object obj)
|
||||||
|
|||||||
@ -7,7 +7,6 @@ namespace Fengling.AuthService.Data;
|
|||||||
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
|
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
|
||||||
: IdentityDbContext<ApplicationUser, ApplicationRole, long>(options)
|
: IdentityDbContext<ApplicationUser, ApplicationRole, long>(options)
|
||||||
{
|
{
|
||||||
public DbSet<Tenant> Tenants { get; set; }
|
|
||||||
public DbSet<AccessLog> AccessLogs { get; set; }
|
public DbSet<AccessLog> AccessLogs { get; set; }
|
||||||
public DbSet<AuditLog> AuditLogs { get; set; }
|
public DbSet<AuditLog> AuditLogs { get; set; }
|
||||||
|
|
||||||
@ -23,27 +22,16 @@ public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options
|
|||||||
|
|
||||||
entity.OwnsOne(e => e.TenantInfo, navigationBuilder =>
|
entity.OwnsOne(e => e.TenantInfo, navigationBuilder =>
|
||||||
{
|
{
|
||||||
navigationBuilder.Property(e => e.Id).HasColumnName("TenantId");
|
navigationBuilder.Property(e => e.TenantCode).HasColumnName("TenantCode");
|
||||||
navigationBuilder.Property(e => e.TenantId).HasColumnName("TenantCode");
|
navigationBuilder.Property(e => e.TenantId).HasColumnName("TenantId");
|
||||||
navigationBuilder.Property(e => e.Name).HasColumnName("TenantName");
|
navigationBuilder.Property(e => e.TenantName).HasColumnName("TenantName");
|
||||||
navigationBuilder.WithOwner();
|
navigationBuilder.WithOwner();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Entity<ApplicationRole>(entity => { entity.Property(e => e.Description).HasMaxLength(200); });
|
builder.Entity<ApplicationRole>(entity => { entity.Property(e => e.Description).HasMaxLength(200); });
|
||||||
|
|
||||||
builder.Entity<Tenant>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id);
|
|
||||||
entity.HasIndex(e => e.TenantId).IsUnique();
|
|
||||||
entity.Property(e => e.TenantId).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.Name).HasMaxLength(100);
|
|
||||||
entity.Property(e => e.ContactName).HasMaxLength(50);
|
|
||||||
entity.Property(e => e.ContactEmail).HasMaxLength(100);
|
|
||||||
entity.Property(e => e.ContactPhone).HasMaxLength(20);
|
|
||||||
entity.Property(e => e.Status).HasMaxLength(20);
|
|
||||||
entity.Property(e => e.Description).HasMaxLength(500);
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Entity<AccessLog>(entity =>
|
builder.Entity<AccessLog>(entity =>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
using Fengling.AuthService.Models;
|
using Fengling.AuthService.Models;
|
||||||
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||||
|
using Fengling.Platform.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using OpenIddict.Abstractions;
|
using OpenIddict.Abstractions;
|
||||||
@ -16,28 +18,11 @@ public static class SeedData
|
|||||||
var applicationManager = scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager>();
|
var applicationManager = scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager>();
|
||||||
var scopeManager = scope.ServiceProvider.GetRequiredService<IOpenIddictScopeManager>();
|
var scopeManager = scope.ServiceProvider.GetRequiredService<IOpenIddictScopeManager>();
|
||||||
|
|
||||||
|
var platformDbContext = scope.ServiceProvider.GetRequiredService<PlatformDbContext>();
|
||||||
|
|
||||||
|
var adminTenant = await platformDbContext.InitializeAsync();
|
||||||
await context.Database.EnsureCreatedAsync();
|
await context.Database.EnsureCreatedAsync();
|
||||||
|
|
||||||
var defaultTenant = await context.Tenants
|
|
||||||
.AsNoTracking()
|
|
||||||
.FirstOrDefaultAsync(t => t.TenantId == "default");
|
|
||||||
if (defaultTenant == null)
|
|
||||||
{
|
|
||||||
defaultTenant = new Tenant
|
|
||||||
{
|
|
||||||
TenantId = "default",
|
|
||||||
Name = "默认租户",
|
|
||||||
ContactName = "系统管理员",
|
|
||||||
ContactEmail = "admin@fengling.local",
|
|
||||||
ContactPhone = "13800138000",
|
|
||||||
MaxUsers = 1000,
|
|
||||||
Description = "系统默认租户",
|
|
||||||
Status = "active",
|
|
||||||
CreatedAt = DateTime.UtcNow
|
|
||||||
};
|
|
||||||
context.Tenants.Add(defaultTenant);
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
var adminRole = await roleManager.FindByNameAsync("Admin");
|
var adminRole = await roleManager.FindByNameAsync("Admin");
|
||||||
if (adminRole == null)
|
if (adminRole == null)
|
||||||
@ -47,7 +32,7 @@ public static class SeedData
|
|||||||
Name = "Admin",
|
Name = "Admin",
|
||||||
DisplayName = "管理员",
|
DisplayName = "管理员",
|
||||||
Description = "System administrator",
|
Description = "System administrator",
|
||||||
TenantId = defaultTenant.Id,
|
TenantId = adminTenant.Id,
|
||||||
IsSystem = true,
|
IsSystem = true,
|
||||||
Permissions = new List<string>
|
Permissions = new List<string>
|
||||||
{
|
{
|
||||||
@ -70,7 +55,7 @@ public static class SeedData
|
|||||||
Name = "User",
|
Name = "User",
|
||||||
DisplayName = "普通用户",
|
DisplayName = "普通用户",
|
||||||
Description = "Regular user",
|
Description = "Regular user",
|
||||||
TenantId = defaultTenant.Id,
|
TenantId = adminTenant.Id,
|
||||||
IsSystem = true,
|
IsSystem = true,
|
||||||
Permissions = new List<string> { "user.view" },
|
Permissions = new List<string> { "user.view" },
|
||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
@ -87,7 +72,7 @@ public static class SeedData
|
|||||||
Email = "admin@fengling.local",
|
Email = "admin@fengling.local",
|
||||||
RealName = "系统管理员",
|
RealName = "系统管理员",
|
||||||
Phone = "13800138000",
|
Phone = "13800138000",
|
||||||
TenantInfo = new TenantInfo(defaultTenant.Id, defaultTenant.TenantId, defaultTenant.Name),
|
TenantInfo = new TenantInfo(adminTenant),
|
||||||
EmailConfirmed = true,
|
EmailConfirmed = true,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
@ -109,7 +94,7 @@ public static class SeedData
|
|||||||
Email = "test@fengling.local",
|
Email = "test@fengling.local",
|
||||||
RealName = "测试用户",
|
RealName = "测试用户",
|
||||||
Phone = "13900139000",
|
Phone = "13900139000",
|
||||||
TenantInfo = new TenantInfo(defaultTenant.Id, defaultTenant.TenantId, defaultTenant.Name),
|
TenantInfo = new TenantInfo(adminTenant.Id, adminTenant.TenantCode, adminTenant.Name),
|
||||||
EmailConfirmed = true,
|
EmailConfirmed = true,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
CreatedTime = DateTime.UtcNow
|
CreatedTime = DateTime.UtcNow
|
||||||
|
|||||||
@ -33,4 +33,9 @@
|
|||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Fengling.Platform\Fengling.Platform.Domain\Fengling.Platform.Domain.csproj" />
|
||||||
|
<ProjectReference Include="..\Fengling.Platform\Fengling.Platform.Infrastructure\Fengling.Platform.Infrastructure.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -13,8 +13,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|||||||
namespace Fengling.AuthService.Migrations
|
namespace Fengling.AuthService.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(ApplicationDbContext))]
|
[DbContext(typeof(ApplicationDbContext))]
|
||||||
[Migration("20260206142720_inital")]
|
[Migration("20260218145654_Initial")]
|
||||||
partial class inital
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
@ -312,141 +312,6 @@ namespace Fengling.AuthService.Migrations
|
|||||||
b.ToTable("AuditLogs");
|
b.ToTable("AuditLogs");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Fengling.AuthService.Models.OAuthApplication", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ClientId")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)");
|
|
||||||
|
|
||||||
b.Property<string>("ClientSecret")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)");
|
|
||||||
|
|
||||||
b.Property<string>("ClientType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)");
|
|
||||||
|
|
||||||
b.Property<string>("ConsentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(500)
|
|
||||||
.HasColumnType("character varying(500)");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)");
|
|
||||||
|
|
||||||
b.PrimitiveCollection<string[]>("GrantTypes")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text[]");
|
|
||||||
|
|
||||||
b.PrimitiveCollection<string[]>("PostLogoutRedirectUris")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text[]");
|
|
||||||
|
|
||||||
b.PrimitiveCollection<string[]>("RedirectUris")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text[]");
|
|
||||||
|
|
||||||
b.PrimitiveCollection<string[]>("Scopes")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text[]");
|
|
||||||
|
|
||||||
b.Property<string>("Status")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("ClientId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("OAuthApplications");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Fengling.AuthService.Models.Tenant", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContactEmail")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)");
|
|
||||||
|
|
||||||
b.Property<string>("ContactName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)");
|
|
||||||
|
|
||||||
b.Property<string>("ContactPhone")
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(500)
|
|
||||||
.HasColumnType("character varying(500)");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<int?>("MaxUsers")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)");
|
|
||||||
|
|
||||||
b.Property<string>("Status")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)");
|
|
||||||
|
|
||||||
b.Property<string>("TenantId")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("TenantId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("Tenants");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<long>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<long>", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -760,25 +625,25 @@ namespace Fengling.AuthService.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("Fengling.AuthService.Models.ApplicationUser", b =>
|
modelBuilder.Entity("Fengling.AuthService.Models.ApplicationUser", b =>
|
||||||
{
|
{
|
||||||
b.OwnsOne("Fengling.AuthService.Models.TenantInfo", "TenantInfo", b1 =>
|
b.OwnsOne("Fengling.Platform.Domain.AggregatesModel.TenantAggregate.TenantInfo", "TenantInfo", b1 =>
|
||||||
{
|
{
|
||||||
b1.Property<long>("ApplicationUserId")
|
b1.Property<long>("ApplicationUserId")
|
||||||
.HasColumnType("bigint");
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b1.Property<long>("Id")
|
b1.Property<string>("TenantCode")
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b1.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("TenantName");
|
|
||||||
|
|
||||||
b1.Property<string>("TenantId")
|
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("TenantCode");
|
.HasColumnName("TenantCode");
|
||||||
|
|
||||||
|
b1.Property<long>("TenantId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b1.Property<string>("TenantName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("TenantName");
|
||||||
|
|
||||||
b1.HasKey("ApplicationUserId");
|
b1.HasKey("ApplicationUserId");
|
||||||
|
|
||||||
b1.ToTable("AspNetUsers");
|
b1.ToTable("AspNetUsers");
|
||||||
@ -8,7 +8,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|||||||
namespace Fengling.AuthService.Migrations
|
namespace Fengling.AuthService.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public partial class inital : Migration
|
public partial class Initial : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
@ -119,31 +119,6 @@ namespace Fengling.AuthService.Migrations
|
|||||||
table.PrimaryKey("PK_AuditLogs", x => x.Id);
|
table.PrimaryKey("PK_AuditLogs", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "OAuthApplications",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
ClientId = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
|
||||||
ClientSecret = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
|
||||||
DisplayName = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
|
||||||
RedirectUris = table.Column<string[]>(type: "text[]", nullable: false),
|
|
||||||
PostLogoutRedirectUris = table.Column<string[]>(type: "text[]", nullable: false),
|
|
||||||
Scopes = table.Column<string[]>(type: "text[]", nullable: false),
|
|
||||||
GrantTypes = table.Column<string[]>(type: "text[]", nullable: false),
|
|
||||||
ClientType = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: false),
|
|
||||||
ConsentType = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: false),
|
|
||||||
Status = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: false),
|
|
||||||
Description = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
|
||||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_OAuthApplications", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "OpenIddictApplications",
|
name: "OpenIddictApplications",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
@ -189,30 +164,6 @@ namespace Fengling.AuthService.Migrations
|
|||||||
table.PrimaryKey("PK_OpenIddictScopes", x => x.Id);
|
table.PrimaryKey("PK_OpenIddictScopes", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Tenants",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
TenantId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
|
||||||
Name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
|
||||||
ContactName = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
|
||||||
ContactEmail = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
|
||||||
ContactPhone = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: true),
|
|
||||||
MaxUsers = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
|
||||||
Description = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
|
||||||
Status = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: false),
|
|
||||||
ExpiresAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
|
||||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "boolean", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Tenants", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "AspNetRoleClaims",
|
name: "AspNetRoleClaims",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
@ -469,12 +420,6 @@ namespace Fengling.AuthService.Migrations
|
|||||||
table: "AuditLogs",
|
table: "AuditLogs",
|
||||||
column: "TenantId");
|
column: "TenantId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_OAuthApplications_ClientId",
|
|
||||||
table: "OAuthApplications",
|
|
||||||
column: "ClientId",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_OpenIddictApplications_ClientId",
|
name: "IX_OpenIddictApplications_ClientId",
|
||||||
table: "OpenIddictApplications",
|
table: "OpenIddictApplications",
|
||||||
@ -507,12 +452,6 @@ namespace Fengling.AuthService.Migrations
|
|||||||
table: "OpenIddictTokens",
|
table: "OpenIddictTokens",
|
||||||
column: "ReferenceId",
|
column: "ReferenceId",
|
||||||
unique: true);
|
unique: true);
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Tenants_TenantId",
|
|
||||||
table: "Tenants",
|
|
||||||
column: "TenantId",
|
|
||||||
unique: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -539,18 +478,12 @@ namespace Fengling.AuthService.Migrations
|
|||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "AuditLogs");
|
name: "AuditLogs");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "OAuthApplications");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "OpenIddictScopes");
|
name: "OpenIddictScopes");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "OpenIddictTokens");
|
name: "OpenIddictTokens");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Tenants");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "AspNetRoles");
|
name: "AspNetRoles");
|
||||||
|
|
||||||
@ -309,73 +309,6 @@ namespace Fengling.AuthService.Migrations
|
|||||||
b.ToTable("AuditLogs");
|
b.ToTable("AuditLogs");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Fengling.AuthService.Models.Tenant", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContactEmail")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)");
|
|
||||||
|
|
||||||
b.Property<string>("ContactName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)");
|
|
||||||
|
|
||||||
b.Property<string>("ContactPhone")
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(500)
|
|
||||||
.HasColumnType("character varying(500)");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<int?>("MaxUsers")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)");
|
|
||||||
|
|
||||||
b.Property<string>("Settings")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Status")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)");
|
|
||||||
|
|
||||||
b.Property<string>("TenantId")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("TenantId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("Tenants");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<long>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<long>", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -689,25 +622,25 @@ namespace Fengling.AuthService.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("Fengling.AuthService.Models.ApplicationUser", b =>
|
modelBuilder.Entity("Fengling.AuthService.Models.ApplicationUser", b =>
|
||||||
{
|
{
|
||||||
b.OwnsOne("Fengling.AuthService.Models.TenantInfo", "TenantInfo", b1 =>
|
b.OwnsOne("Fengling.Platform.Domain.AggregatesModel.TenantAggregate.TenantInfo", "TenantInfo", b1 =>
|
||||||
{
|
{
|
||||||
b1.Property<long>("ApplicationUserId")
|
b1.Property<long>("ApplicationUserId")
|
||||||
.HasColumnType("bigint");
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b1.Property<long>("Id")
|
b1.Property<string>("TenantCode")
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b1.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("TenantName");
|
|
||||||
|
|
||||||
b1.Property<string>("TenantId")
|
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("TenantCode");
|
.HasColumnName("TenantCode");
|
||||||
|
|
||||||
|
b1.Property<long>("TenantId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b1.Property<string>("TenantName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("TenantName");
|
||||||
|
|
||||||
b1.HasKey("ApplicationUserId");
|
b1.HasKey("ApplicationUserId");
|
||||||
|
|
||||||
b1.ToTable("AspNetUsers");
|
b1.ToTable("AspNetUsers");
|
||||||
|
|||||||
@ -1,63 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Fengling.AuthService.Models;
|
|
||||||
|
|
||||||
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.AuthService.Models;
|
|
||||||
|
|
||||||
public record TenantInfo(long Id, string TenantId, string Name);
|
|
||||||
Loading…
Reference in New Issue
Block a user