fix: identity 登录并发改为 xmin
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 8s
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 8s
移除 identity_users 对 RowVersion 列的依赖,改用 PostgreSQL xmin 作为并发令牌,修复线上登录因缺失 RowVersion 列导致的 500 错误。
This commit is contained in:
@@ -50,9 +50,7 @@ public sealed record UpdateIdentityUserCommand : IRequest<UserDetailDto?>
|
|||||||
public string[]? RoleIds { get; init; }
|
public string[]? RoleIds { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 并发控制版本。
|
/// 并发控制版本(兼容字段,当前由数据库 xmin 托管)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
public byte[]? RowVersion { get; init; }
|
||||||
[MinLength(1)]
|
|
||||||
public byte[] RowVersion { get; init; } = Array.Empty<byte>();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ public sealed class UpdateIdentityUserCommandHandler(
|
|||||||
user.Phone = phone;
|
user.Phone = phone;
|
||||||
user.Email = email;
|
user.Email = email;
|
||||||
user.Avatar = string.IsNullOrWhiteSpace(request.Avatar) ? null : request.Avatar.Trim();
|
user.Avatar = string.IsNullOrWhiteSpace(request.Avatar) ? null : request.Avatar.Trim();
|
||||||
user.RowVersion = request.RowVersion;
|
|
||||||
|
|
||||||
// 6. 构建操作日志消息
|
// 6. 构建操作日志消息
|
||||||
var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName)
|
var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ public sealed class UpdateIdentityUserCommandValidator : AbstractValidator<Updat
|
|||||||
RuleFor(x => x.UserId).GreaterThan(0);
|
RuleFor(x => x.UserId).GreaterThan(0);
|
||||||
RuleFor(x => x.DisplayName).NotEmpty().MaximumLength(64);
|
RuleFor(x => x.DisplayName).NotEmpty().MaximumLength(64);
|
||||||
RuleFor(x => x.Avatar).MaximumLength(512);
|
RuleFor(x => x.Avatar).MaximumLength(512);
|
||||||
RuleFor(x => x.RowVersion).NotEmpty();
|
|
||||||
RuleFor(x => x.TenantId).GreaterThan(0).When(x => x.TenantId.HasValue);
|
RuleFor(x => x.TenantId).GreaterThan(0).When(x => x.TenantId.HasValue);
|
||||||
RuleForEach(x => x.RoleIds)
|
RuleForEach(x => x.RoleIds)
|
||||||
.Must(value => long.TryParse(value, out _))
|
.Must(value => long.TryParse(value, out _))
|
||||||
|
|||||||
@@ -104,10 +104,12 @@ public sealed class IdentityDbContext(
|
|||||||
builder.Property(x => x.LastLoginAt);
|
builder.Property(x => x.LastLoginAt);
|
||||||
builder.Property(x => x.MustChangePassword).IsRequired();
|
builder.Property(x => x.MustChangePassword).IsRequired();
|
||||||
builder.Property(x => x.Avatar).HasColumnType("text");
|
builder.Property(x => x.Avatar).HasColumnType("text");
|
||||||
builder.Property(x => x.RowVersion)
|
builder.Ignore(x => x.RowVersion);
|
||||||
.IsRowVersion()
|
builder.Property<uint>("xmin")
|
||||||
.IsConcurrencyToken()
|
.HasColumnName("xmin")
|
||||||
.HasColumnType("bytea");
|
.HasColumnType("xid")
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.IsConcurrencyToken();
|
||||||
builder.Property(x => x.TenantId).IsRequired();
|
builder.Property(x => x.TenantId).IsRequired();
|
||||||
ConfigureAuditableEntity(builder);
|
ConfigureAuditableEntity(builder);
|
||||||
ConfigureSoftDeleteEntity(builder);
|
ConfigureSoftDeleteEntity(builder);
|
||||||
|
|||||||
Reference in New Issue
Block a user