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.Models;
|
||||
using Fengling.AuthService.ViewModels;
|
||||
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||
using Fengling.Platform.Infrastructure;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
@ -10,25 +12,14 @@ using Microsoft.EntityFrameworkCore;
|
||||
namespace Fengling.AuthService.Controllers;
|
||||
|
||||
[Route("account")]
|
||||
public class AccountController : Controller
|
||||
public class AccountController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
ApplicationDbContext dbContext,
|
||||
ILogger<AccountController> logger,
|
||||
PlatformDbContext platformDbContext)
|
||||
: Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly ApplicationDbContext _dbContext;
|
||||
private readonly ILogger<AccountController> _logger;
|
||||
|
||||
public AccountController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
ApplicationDbContext dbContext,
|
||||
ILogger<AccountController> logger)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
_dbContext = dbContext;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet("login")]
|
||||
public IActionResult Login(string returnUrl = "/")
|
||||
{
|
||||
@ -44,14 +35,14 @@ public class AccountController : Controller
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var user = await _userManager.FindByNameAsync(model.Username);
|
||||
var user = await userManager.FindByNameAsync(model.Username);
|
||||
if (user == null || user.IsDeleted)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "用户名或密码错误");
|
||||
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.IsLockedOut)
|
||||
@ -83,12 +74,12 @@ public class AccountController : Controller
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var defaultTenant = await _dbContext.Tenants
|
||||
.FirstOrDefaultAsync(t => t.TenantId == "default");
|
||||
var tenant = await platformDbContext.Tenants
|
||||
.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);
|
||||
}
|
||||
|
||||
@ -98,10 +89,10 @@ public class AccountController : Controller
|
||||
Email = model.Email,
|
||||
NormalizedUserName = model.Username.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)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
@ -111,7 +102,7 @@ public class AccountController : Controller
|
||||
return View(model);
|
||||
}
|
||||
|
||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
await signInManager.SignInAsync(user, isPersistent: false);
|
||||
return LocalRedirect(model.ReturnUrl);
|
||||
}
|
||||
|
||||
@ -127,7 +118,7 @@ public class AccountController : Controller
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> LogoutPost()
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
await signInManager.SignOutAsync();
|
||||
return Redirect("/");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using Fengling.AuthService.Data;
|
||||
using Fengling.AuthService.Models;
|
||||
using Fengling.Platform.Infrastructure;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -10,21 +11,13 @@ namespace Fengling.AuthService.Controllers;
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize]
|
||||
public class StatsController : ControllerBase
|
||||
public class StatsController(
|
||||
ApplicationDbContext context,
|
||||
IOpenIddictApplicationManager applicationManager,
|
||||
ILogger<StatsController> logger,
|
||||
PlatformDbContext platformDbContext)
|
||||
: ControllerBase
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly IOpenIddictApplicationManager _applicationManager;
|
||||
private readonly ILogger<StatsController> _logger;
|
||||
|
||||
public StatsController(
|
||||
ApplicationDbContext context,
|
||||
IOpenIddictApplicationManager applicationManager,
|
||||
ILogger<StatsController> logger)
|
||||
{
|
||||
_context = context;
|
||||
_applicationManager = applicationManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet("dashboard")]
|
||||
public async Task<ActionResult<object>> GetDashboardStats()
|
||||
@ -32,10 +25,10 @@ public class StatsController : ControllerBase
|
||||
var today = DateTime.UtcNow.Date;
|
||||
var tomorrow = today.AddDays(1);
|
||||
|
||||
var userCount = await _context.Users.CountAsync(u => !u.IsDeleted);
|
||||
var tenantCount = await _context.Tenants.CountAsync(t => !t.IsDeleted);
|
||||
var userCount = await context.Users.CountAsync(u => !u.IsDeleted);
|
||||
var tenantCount = await platformDbContext.Tenants.CountAsync(t => !t.Deleted);
|
||||
var oauthClientCount = await CountOAuthClientsAsync();
|
||||
var todayAccessCount = await _context.AccessLogs
|
||||
var todayAccessCount = await context.AccessLogs
|
||||
.CountAsync(l => l.CreatedAt >= today && l.CreatedAt < tomorrow);
|
||||
|
||||
return Ok(new
|
||||
@ -50,7 +43,7 @@ public class StatsController : ControllerBase
|
||||
private async Task<int> CountOAuthClientsAsync()
|
||||
{
|
||||
var count = 0;
|
||||
var applications = _applicationManager.ListAsync();
|
||||
var applications = applicationManager.ListAsync();
|
||||
await foreach (var _ in applications)
|
||||
{
|
||||
count++;
|
||||
|
||||
@ -6,49 +6,42 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||
using Fengling.Platform.Infrastructure;
|
||||
|
||||
namespace Fengling.AuthService.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize]
|
||||
public class TenantsController : ControllerBase
|
||||
public class TenantsController(
|
||||
ApplicationDbContext context,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
ILogger<TenantsController> logger,
|
||||
PlatformDbContext platformDbContext)
|
||||
: ControllerBase
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly ILogger<TenantsController> _logger;
|
||||
|
||||
public TenantsController(
|
||||
ApplicationDbContext context,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
ILogger<TenantsController> logger)
|
||||
{
|
||||
_context = context;
|
||||
_userManager = userManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<object>> GetTenants(
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 10,
|
||||
[FromQuery] string? name = null,
|
||||
[FromQuery] string? tenantId = null,
|
||||
[FromQuery] string? status = null)
|
||||
[FromQuery] string? tenantCode = null,
|
||||
[FromQuery] TenantStatus? status = null)
|
||||
{
|
||||
var query = _context.Tenants.AsQueryable();
|
||||
var query = platformDbContext.Tenants.AsQueryable();
|
||||
|
||||
if (!string.IsNullOrEmpty(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);
|
||||
}
|
||||
@ -64,11 +57,11 @@ public class TenantsController : ControllerBase
|
||||
|
||||
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
|
||||
{
|
||||
id = tenant.Id,
|
||||
tenantId = tenant.TenantId,
|
||||
tenantId = tenant.Id,
|
||||
name = tenant.Name,
|
||||
contactName = tenant.ContactName,
|
||||
contactEmail = tenant.ContactEmail,
|
||||
@ -92,9 +85,9 @@ public class TenantsController : ControllerBase
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
return NotFound();
|
||||
@ -103,7 +96,7 @@ public class TenantsController : ControllerBase
|
||||
return Ok(new
|
||||
{
|
||||
id = tenant.Id,
|
||||
tenantId = tenant.TenantId,
|
||||
tenantId = tenant.Id,
|
||||
name = tenant.Name,
|
||||
contactName = tenant.ContactName,
|
||||
contactEmail = tenant.ContactEmail,
|
||||
@ -118,16 +111,19 @@ public class TenantsController : ControllerBase
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var users = await _context.Users
|
||||
.Where(u => u.TenantInfo.Id == tenant.Id && !u.IsDeleted)
|
||||
var users = await context.Users
|
||||
.Where(u =>
|
||||
u.TenantInfo.TenantId == tenant.Id
|
||||
&& !u.IsDeleted)
|
||||
.ToListAsync();
|
||||
|
||||
var result = users.Select(async u => new
|
||||
@ -136,8 +132,8 @@ public class TenantsController : ControllerBase
|
||||
userName = u.UserName,
|
||||
email = u.Email,
|
||||
realName = u.RealName,
|
||||
tenantId = u.TenantInfo.Id,
|
||||
roles = await _userManager.GetRolesAsync(u),
|
||||
tenantId = u.TenantInfo.TenantId,
|
||||
roles = await userManager.GetRolesAsync(u),
|
||||
isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow,
|
||||
createdAt = u.CreatedTime,
|
||||
});
|
||||
@ -146,15 +142,16 @@ public class TenantsController : ControllerBase
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var roles = await _context.Roles
|
||||
var roles = await context.Roles
|
||||
.Where(r => r.TenantId == tenant.Id)
|
||||
.ToListAsync();
|
||||
|
||||
@ -169,9 +166,10 @@ public class TenantsController : ControllerBase
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
return NotFound();
|
||||
@ -191,15 +189,16 @@ public class TenantsController : ControllerBase
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
@ -207,24 +206,14 @@ public class TenantsController : ControllerBase
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Tenant>> CreateTenant(CreateTenantDto dto)
|
||||
{
|
||||
var tenant = new Tenant
|
||||
{
|
||||
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,
|
||||
};
|
||||
var tenant = new Tenant(dto.TenantCode, dto.TenantName, dto.ContactName, dto.ContactEmail, dto.ContactPhone,
|
||||
dto.MaxUsers, dto.Description, dto.ExpiresAt);
|
||||
|
||||
_context.Tenants.Add(tenant);
|
||||
await _context.SaveChangesAsync();
|
||||
platformDbContext.Tenants.Add(tenant);
|
||||
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);
|
||||
}
|
||||
@ -232,27 +221,20 @@ public class TenantsController : ControllerBase
|
||||
[HttpPut("{id}")]
|
||||
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)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
@ -260,7 +242,7 @@ public class TenantsController : ControllerBase
|
||||
[HttpDelete("{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)
|
||||
{
|
||||
return NotFound();
|
||||
@ -268,22 +250,23 @@ public class TenantsController : ControllerBase
|
||||
|
||||
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)
|
||||
{
|
||||
user.IsDeleted = true;
|
||||
user.UpdatedTime = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
tenant.IsDeleted = true;
|
||||
await _context.SaveChangesAsync();
|
||||
tenant.Delete();
|
||||
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();
|
||||
}
|
||||
|
||||
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 tenantId = User.FindFirstValue("TenantId");
|
||||
@ -303,23 +286,21 @@ public class TenantsController : ControllerBase
|
||||
NewValue = newValue,
|
||||
};
|
||||
|
||||
_context.AuditLogs.Add(log);
|
||||
await _context.SaveChangesAsync();
|
||||
context.AuditLogs.Add(log);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateTenantDto
|
||||
{
|
||||
public string TenantId { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string ContactName { get; set; } = string.Empty;
|
||||
public string ContactEmail { get; set; } = string.Empty;
|
||||
public string? ContactPhone { get; set; }
|
||||
public int? MaxUsers { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string Status { get; set; } = "active";
|
||||
public DateTime? ExpiresAt { get; set; }
|
||||
}
|
||||
public record CreateTenantDto(
|
||||
string TenantCode,
|
||||
string TenantName,
|
||||
string ContactName,
|
||||
string ContactEmail,
|
||||
string ContactPhone,
|
||||
int? MaxUsers,
|
||||
string? Description,
|
||||
string Status,
|
||||
DateTime? ExpiresAt);
|
||||
|
||||
public class UpdateTenantDto
|
||||
{
|
||||
|
||||
@ -5,30 +5,22 @@ using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Security.Claims;
|
||||
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||
using Fengling.Platform.Infrastructure;
|
||||
|
||||
namespace Fengling.AuthService.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize]
|
||||
public class UsersController : ControllerBase
|
||||
public class UsersController(
|
||||
ApplicationDbContext context,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
RoleManager<ApplicationRole> roleManager,
|
||||
ILogger<UsersController> logger,
|
||||
PlatformDbContext platformDbContext)
|
||||
: ControllerBase
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly RoleManager<ApplicationRole> _roleManager;
|
||||
private readonly ILogger<UsersController> _logger;
|
||||
|
||||
public UsersController(
|
||||
ApplicationDbContext context,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
RoleManager<ApplicationRole> roleManager,
|
||||
ILogger<UsersController> logger)
|
||||
{
|
||||
_context = context;
|
||||
_userManager = userManager;
|
||||
_roleManager = roleManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<object>> GetUsers(
|
||||
@ -36,9 +28,9 @@ public class UsersController : ControllerBase
|
||||
[FromQuery] int pageSize = 10,
|
||||
[FromQuery] string? userName = 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))
|
||||
{
|
||||
@ -50,9 +42,9 @@ public class UsersController : ControllerBase
|
||||
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();
|
||||
@ -69,8 +61,8 @@ public class UsersController : ControllerBase
|
||||
email = u.Email,
|
||||
realName = u.RealName,
|
||||
phone = u.Phone,
|
||||
tenantId = u.TenantInfo.Id,
|
||||
roles = (await _userManager.GetRolesAsync(u)).ToList(),
|
||||
tenantId = u.TenantInfo.TenantId,
|
||||
roles = (await userManager.GetRolesAsync(u)).ToList(),
|
||||
emailConfirmed = u.EmailConfirmed,
|
||||
isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow,
|
||||
createdAt = u.CreatedTime,
|
||||
@ -88,13 +80,13 @@ public class UsersController : ControllerBase
|
||||
[HttpGet("{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)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var roles = await _userManager.GetRolesAsync(user);
|
||||
var roles = await userManager.GetRolesAsync(user);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
@ -103,7 +95,7 @@ public class UsersController : ControllerBase
|
||||
email = user.Email,
|
||||
realName = user.RealName,
|
||||
phone = user.Phone,
|
||||
tenantId = user.TenantInfo.Id,
|
||||
tenantId = user.TenantInfo.TenantId,
|
||||
roles,
|
||||
emailConfirmed = user.EmailConfirmed,
|
||||
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)
|
||||
{
|
||||
var tenantId = dto.TenantId ?? 0;
|
||||
Tenant tenant = null;
|
||||
Tenant? tenant = null;
|
||||
|
||||
if (tenantId != 0)
|
||||
{
|
||||
tenant = await _context.Tenants.FindAsync(tenantId);
|
||||
tenant = await platformDbContext.Tenants.FindAsync(tenantId);
|
||||
if (tenant == null)
|
||||
{
|
||||
return BadRequest("Invalid tenant ID");
|
||||
@ -132,33 +124,33 @@ public class UsersController : ControllerBase
|
||||
Email = dto.Email,
|
||||
RealName = dto.RealName,
|
||||
Phone = dto.Phone,
|
||||
TenantInfo = new TenantInfo(tenantId, tenant?.TenantId ?? "default", tenant?.Name ?? "默认租户"),
|
||||
TenantInfo = new TenantInfo(tenant!),
|
||||
EmailConfirmed = dto.EmailConfirmed,
|
||||
CreatedTime = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
var result = await _userManager.CreateAsync(user, dto.Password);
|
||||
var result = await userManager.CreateAsync(user, dto.Password);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return BadRequest(result.Errors);
|
||||
}
|
||||
|
||||
if (dto.RoleIds != null && dto.RoleIds.Any())
|
||||
if (dto.RoleIds.Any())
|
||||
{
|
||||
foreach (var roleId in dto.RoleIds)
|
||||
{
|
||||
var role = await _roleManager.FindByIdAsync(roleId.ToString());
|
||||
var role = await roleManager.FindByIdAsync(roleId.ToString());
|
||||
if (role != null)
|
||||
{
|
||||
await _userManager.AddToRoleAsync(user, role.Name!);
|
||||
await userManager.AddToRoleAsync(user, role.Name!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dto.IsActive)
|
||||
{
|
||||
await _userManager.SetLockoutEnabledAsync(user, true);
|
||||
await _userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
||||
await userManager.SetLockoutEnabledAsync(user, true);
|
||||
await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
||||
}
|
||||
|
||||
await CreateAuditLog("user", "create", "User", user.Id, user.UserName, null, SerializeToJson(dto));
|
||||
@ -169,7 +161,7 @@ public class UsersController : ControllerBase
|
||||
[HttpPut("{id}")]
|
||||
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)
|
||||
{
|
||||
return NotFound();
|
||||
@ -185,16 +177,16 @@ public class UsersController : ControllerBase
|
||||
|
||||
if (dto.IsActive)
|
||||
{
|
||||
await _userManager.SetLockoutEnabledAsync(user, false);
|
||||
await _userManager.SetLockoutEndDateAsync(user, null);
|
||||
await userManager.SetLockoutEnabledAsync(user, false);
|
||||
await userManager.SetLockoutEndDateAsync(user, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _userManager.SetLockoutEnabledAsync(user, true);
|
||||
await _userManager.SetLockoutEndDateAsync(user, DateTimeOffset.MaxValue);
|
||||
await userManager.SetLockoutEnabledAsync(user, true);
|
||||
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));
|
||||
|
||||
@ -204,14 +196,14 @@ public class UsersController : ControllerBase
|
||||
[HttpPut("{id}/password")]
|
||||
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)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var token = await _userManager.GeneratePasswordResetTokenAsync(user);
|
||||
var result = await _userManager.ResetPasswordAsync(user, token, dto.NewPassword);
|
||||
var token = await userManager.GeneratePasswordResetTokenAsync(user);
|
||||
var result = await userManager.ResetPasswordAsync(user, token, dto.NewPassword);
|
||||
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
@ -226,7 +218,7 @@ public class UsersController : ControllerBase
|
||||
[HttpDelete("{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)
|
||||
{
|
||||
return NotFound();
|
||||
@ -235,7 +227,7 @@ public class UsersController : ControllerBase
|
||||
var oldValue = System.Text.Json.JsonSerializer.Serialize(user);
|
||||
user.IsDeleted = true;
|
||||
user.UpdatedTime = DateTime.UtcNow;
|
||||
await _context.SaveChangesAsync();
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
await CreateAuditLog("user", "delete", "User", user.Id, user.UserName, oldValue);
|
||||
|
||||
@ -262,8 +254,8 @@ public class UsersController : ControllerBase
|
||||
NewValue = newValue,
|
||||
};
|
||||
|
||||
_context.AuditLogs.Add(log);
|
||||
await _context.SaveChangesAsync();
|
||||
context.AuditLogs.Add(log);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private string SerializeToJson(object obj)
|
||||
|
||||
@ -7,7 +7,6 @@ namespace Fengling.AuthService.Data;
|
||||
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; }
|
||||
|
||||
@ -23,27 +22,16 @@ public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options
|
||||
|
||||
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.Property(e => e.TenantCode).HasColumnName("TenantCode");
|
||||
navigationBuilder.Property(e => e.TenantId).HasColumnName("TenantId");
|
||||
navigationBuilder.Property(e => e.TenantName).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 =>
|
||||
{
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using Fengling.AuthService.Models;
|
||||
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||
using Fengling.Platform.Infrastructure;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using OpenIddict.Abstractions;
|
||||
@ -16,28 +18,11 @@ public static class SeedData
|
||||
var applicationManager = scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager>();
|
||||
var scopeManager = scope.ServiceProvider.GetRequiredService<IOpenIddictScopeManager>();
|
||||
|
||||
var platformDbContext = scope.ServiceProvider.GetRequiredService<PlatformDbContext>();
|
||||
|
||||
var adminTenant = await platformDbContext.InitializeAsync();
|
||||
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");
|
||||
if (adminRole == null)
|
||||
@ -47,7 +32,7 @@ public static class SeedData
|
||||
Name = "Admin",
|
||||
DisplayName = "管理员",
|
||||
Description = "System administrator",
|
||||
TenantId = defaultTenant.Id,
|
||||
TenantId = adminTenant.Id,
|
||||
IsSystem = true,
|
||||
Permissions = new List<string>
|
||||
{
|
||||
@ -70,7 +55,7 @@ public static class SeedData
|
||||
Name = "User",
|
||||
DisplayName = "普通用户",
|
||||
Description = "Regular user",
|
||||
TenantId = defaultTenant.Id,
|
||||
TenantId = adminTenant.Id,
|
||||
IsSystem = true,
|
||||
Permissions = new List<string> { "user.view" },
|
||||
CreatedTime = DateTime.UtcNow
|
||||
@ -87,7 +72,7 @@ public static class SeedData
|
||||
Email = "admin@fengling.local",
|
||||
RealName = "系统管理员",
|
||||
Phone = "13800138000",
|
||||
TenantInfo = new TenantInfo(defaultTenant.Id, defaultTenant.TenantId, defaultTenant.Name),
|
||||
TenantInfo = new TenantInfo(adminTenant),
|
||||
EmailConfirmed = true,
|
||||
IsDeleted = false,
|
||||
CreatedTime = DateTime.UtcNow
|
||||
@ -109,7 +94,7 @@ public static class SeedData
|
||||
Email = "test@fengling.local",
|
||||
RealName = "测试用户",
|
||||
Phone = "13900139000",
|
||||
TenantInfo = new TenantInfo(defaultTenant.Id, defaultTenant.TenantId, defaultTenant.Name),
|
||||
TenantInfo = new TenantInfo(adminTenant.Id, adminTenant.TenantCode, adminTenant.Name),
|
||||
EmailConfirmed = true,
|
||||
IsDeleted = false,
|
||||
CreatedTime = DateTime.UtcNow
|
||||
@ -140,19 +125,19 @@ public static class SeedData
|
||||
};
|
||||
|
||||
foreach (var uri in new[]
|
||||
{
|
||||
"http://localhost:5777/auth/callback",
|
||||
"https://console.fengling.local/auth/callback"
|
||||
})
|
||||
{
|
||||
"http://localhost:5777/auth/callback",
|
||||
"https://console.fengling.local/auth/callback"
|
||||
})
|
||||
{
|
||||
descriptor.RedirectUris.Add(new Uri(uri));
|
||||
}
|
||||
|
||||
foreach (var uri in new[]
|
||||
{
|
||||
"http://localhost:5777/",
|
||||
"https://console.fengling.local/"
|
||||
})
|
||||
{
|
||||
"http://localhost:5777/",
|
||||
"https://console.fengling.local/"
|
||||
})
|
||||
{
|
||||
descriptor.PostLogoutRedirectUris.Add(new Uri(uri));
|
||||
}
|
||||
|
||||
@ -33,4 +33,9 @@
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</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>
|
||||
|
||||
@ -13,8 +13,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace Fengling.AuthService.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20260206142720_inital")]
|
||||
partial class inital
|
||||
[Migration("20260218145654_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -312,141 +312,6 @@ namespace Fengling.AuthService.Migrations
|
||||
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 =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@ -760,25 +625,25 @@ namespace Fengling.AuthService.Migrations
|
||||
|
||||
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")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b1.Property<long>("Id")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("TenantId");
|
||||
|
||||
b1.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("TenantName");
|
||||
|
||||
b1.Property<string>("TenantId")
|
||||
b1.Property<string>("TenantCode")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("TenantCode");
|
||||
|
||||
b1.Property<long>("TenantId")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("TenantId");
|
||||
|
||||
b1.Property<string>("TenantName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("TenantName");
|
||||
|
||||
b1.HasKey("ApplicationUserId");
|
||||
|
||||
b1.ToTable("AspNetUsers");
|
||||
@ -8,7 +8,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace Fengling.AuthService.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class inital : Migration
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
@ -119,31 +119,6 @@ namespace Fengling.AuthService.Migrations
|
||||
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(
|
||||
name: "OpenIddictApplications",
|
||||
columns: table => new
|
||||
@ -189,30 +164,6 @@ namespace Fengling.AuthService.Migrations
|
||||
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(
|
||||
name: "AspNetRoleClaims",
|
||||
columns: table => new
|
||||
@ -469,12 +420,6 @@ namespace Fengling.AuthService.Migrations
|
||||
table: "AuditLogs",
|
||||
column: "TenantId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OAuthApplications_ClientId",
|
||||
table: "OAuthApplications",
|
||||
column: "ClientId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictApplications_ClientId",
|
||||
table: "OpenIddictApplications",
|
||||
@ -507,12 +452,6 @@ namespace Fengling.AuthService.Migrations
|
||||
table: "OpenIddictTokens",
|
||||
column: "ReferenceId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tenants_TenantId",
|
||||
table: "Tenants",
|
||||
column: "TenantId",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -539,18 +478,12 @@ namespace Fengling.AuthService.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "AuditLogs");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OAuthApplications");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictScopes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Tenants");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoles");
|
||||
|
||||
@ -309,73 +309,6 @@ namespace Fengling.AuthService.Migrations
|
||||
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 =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@ -689,25 +622,25 @@ namespace Fengling.AuthService.Migrations
|
||||
|
||||
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")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b1.Property<long>("Id")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("TenantId");
|
||||
|
||||
b1.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("TenantName");
|
||||
|
||||
b1.Property<string>("TenantId")
|
||||
b1.Property<string>("TenantCode")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("TenantCode");
|
||||
|
||||
b1.Property<long>("TenantId")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("TenantId");
|
||||
|
||||
b1.Property<string>("TenantName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("TenantName");
|
||||
|
||||
b1.HasKey("ApplicationUserId");
|
||||
|
||||
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