forked from gongxuegit/tiku-backend.net
feat(security): add distributed authorization foundation
This commit is contained in:
13
Tiku.Infrastructure/Messaging/MessagingOptions.cs
Normal file
13
Tiku.Infrastructure/Messaging/MessagingOptions.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Tiku.Infrastructure.Messaging;
|
||||
|
||||
public sealed class MessagingOptions
|
||||
{
|
||||
public string Host { get; set; } = string.Empty;
|
||||
public string VirtualHost { get; set; } = "/";
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public bool ConfigureConsumers { get; set; }
|
||||
|
||||
public bool IsConfigured => Uri.TryCreate(Host, UriKind.Absolute, out var uri) &&
|
||||
uri.Scheme is "rabbitmq" or "amqp" or "amqps";
|
||||
}
|
||||
70
Tiku.Infrastructure/Messaging/SecurityEventPublisher.cs
Normal file
70
Tiku.Infrastructure/Messaging/SecurityEventPublisher.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using MassTransit;
|
||||
using Tiku.Contracts;
|
||||
|
||||
namespace Tiku.Infrastructure.Messaging;
|
||||
|
||||
public interface ISecurityEventPublisher
|
||||
{
|
||||
Task AuthorizationChangedAsync(
|
||||
Guid? tenantId,
|
||||
Guid? userId,
|
||||
string changeKind,
|
||||
long version,
|
||||
string correlationId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task CapabilityChangedAsync(
|
||||
Guid tenantId,
|
||||
string moduleCode,
|
||||
string changeKind,
|
||||
long version,
|
||||
string correlationId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task MembershipChangedAsync(
|
||||
Guid tenantId,
|
||||
Guid userId,
|
||||
string previousStatus,
|
||||
string currentStatus,
|
||||
string correlationId,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
internal sealed class NullSecurityEventPublisher : ISecurityEventPublisher
|
||||
{
|
||||
public Task AuthorizationChangedAsync(
|
||||
Guid? tenantId, Guid? userId, string changeKind, long version,
|
||||
string correlationId, CancellationToken cancellationToken = default) => Task.CompletedTask;
|
||||
|
||||
public Task CapabilityChangedAsync(
|
||||
Guid tenantId, string moduleCode, string changeKind, long version,
|
||||
string correlationId, CancellationToken cancellationToken = default) => Task.CompletedTask;
|
||||
|
||||
public Task MembershipChangedAsync(
|
||||
Guid tenantId, Guid userId, string previousStatus, string currentStatus,
|
||||
string correlationId, CancellationToken cancellationToken = default) => Task.CompletedTask;
|
||||
}
|
||||
|
||||
internal sealed class MassTransitSecurityEventPublisher(IPublishEndpoint publishEndpoint) : ISecurityEventPublisher
|
||||
{
|
||||
public Task AuthorizationChangedAsync(
|
||||
Guid? tenantId, Guid? userId, string changeKind, long version,
|
||||
string correlationId, CancellationToken cancellationToken = default) =>
|
||||
publishEndpoint.Publish(new AuthorizationStateChangedV1(
|
||||
Guid.NewGuid(), tenantId, userId, changeKind, version,
|
||||
DateTimeOffset.UtcNow, correlationId), cancellationToken);
|
||||
|
||||
public Task CapabilityChangedAsync(
|
||||
Guid tenantId, string moduleCode, string changeKind, long version,
|
||||
string correlationId, CancellationToken cancellationToken = default) =>
|
||||
publishEndpoint.Publish(new TenantCapabilityChangedV1(
|
||||
Guid.NewGuid(), tenantId, moduleCode, changeKind, version,
|
||||
DateTimeOffset.UtcNow, correlationId), cancellationToken);
|
||||
|
||||
public Task MembershipChangedAsync(
|
||||
Guid tenantId, Guid userId, string previousStatus, string currentStatus,
|
||||
string correlationId, CancellationToken cancellationToken = default) =>
|
||||
publishEndpoint.Publish(new MembershipLifecycleChangedV1(
|
||||
Guid.NewGuid(), tenantId, userId, previousStatus, currentStatus,
|
||||
DateTimeOffset.UtcNow, correlationId), cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using MassTransit;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Contracts;
|
||||
|
||||
namespace Tiku.Infrastructure.Messaging;
|
||||
|
||||
internal sealed class SecurityStateChangedConsumer(IRedisSecurityStore redisSecurityStore) :
|
||||
IConsumer<AuthorizationStateChangedV1>,
|
||||
IConsumer<TenantCapabilityChangedV1>,
|
||||
IConsumer<MembershipLifecycleChangedV1>
|
||||
{
|
||||
public Task Consume(ConsumeContext<AuthorizationStateChangedV1> context) =>
|
||||
redisSecurityStore.SetInvalidationVersionAsync(
|
||||
"authorization", context.Message.TenantId, context.Message.UserId,
|
||||
context.Message.Version, context.CancellationToken);
|
||||
|
||||
public Task Consume(ConsumeContext<TenantCapabilityChangedV1> context) =>
|
||||
redisSecurityStore.SetInvalidationVersionAsync(
|
||||
$"capability-{context.Message.ModuleCode}", context.Message.TenantId, null,
|
||||
context.Message.Version, context.CancellationToken);
|
||||
|
||||
public Task Consume(ConsumeContext<MembershipLifecycleChangedV1> context) =>
|
||||
redisSecurityStore.SetInvalidationVersionAsync(
|
||||
"membership", context.Message.TenantId, context.Message.UserId,
|
||||
context.Message.OccurredAt.ToUnixTimeMilliseconds(), context.CancellationToken);
|
||||
}
|
||||
Reference in New Issue
Block a user