refactor(platform): split control plane services
This commit is contained in:
@@ -26,6 +26,7 @@ internal static class ApiPresentationExtensions
|
||||
services.AddScoped<DirectContentActorResolver>();
|
||||
services.AddScoped<CommerceAdminActorResolver>();
|
||||
services.AddScoped<LearningActorResolver>();
|
||||
services.AddScoped<PlatformAdminActorResolver>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
15
Tiku.Api/Controllers/PlatformAdminActorResolver.cs
Normal file
15
Tiku.Api/Controllers/PlatformAdminActorResolver.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
|
||||
namespace Tiku.Api.Controllers;
|
||||
|
||||
public sealed class PlatformAdminActorResolver(ICurrentUser currentUser)
|
||||
{
|
||||
internal PlatformAdminActor Resolve()
|
||||
{
|
||||
if (currentUser.UserId is not { } userId)
|
||||
throw new PlatformAdminException("Platform admin actor was not resolved.", "platform_access_denied");
|
||||
|
||||
return new PlatformAdminActor(userId);
|
||||
}
|
||||
}
|
||||
@@ -1,358 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Tiku.Api.Contracts;
|
||||
using Tiku.Api.OpenApi;
|
||||
using Tiku.Application.Auth;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Tags("平台端-平台管理")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformDashboardView)]
|
||||
[Produces("application/json")]
|
||||
[Route("api/platform")]
|
||||
public sealed class PlatformAdminController(
|
||||
IPlatformAdminService platformAdminService,
|
||||
IPlatformApprovalService approvalService,
|
||||
IAuthAdministrationService authAdministrationService,
|
||||
ICurrentUser currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet("overview")]
|
||||
[EndpointSummary("查询平台经营概览")]
|
||||
[ProducesResponseType<PlatformOverview>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformOverview>> Overview(CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetOverviewAsync(ResolveActor(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("tenants")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("查询平台租户列表")]
|
||||
[ProducesResponseType<PlatformTenantList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformTenantList>> Tenants(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetTenantsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("tenants")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("创建平台租户")]
|
||||
[ProducesResponseType<PlatformTenantProvisioningResult>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformTenantProvisioningResult>> CreateTenant(
|
||||
CreatePlatformTenantDto request,
|
||||
[FromHeader(Name = "Idempotency-Key")] [Required]
|
||||
string idempotencyKey,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.CreateTenantAsync(
|
||||
ResolveActor(),
|
||||
request.ToCommand(idempotencyKey),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("tenants/{tenantId:guid}/primary-domain")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("更正租户主域名")]
|
||||
public Task<PlatformTenantDomainItem> ReplacePrimaryDomain(
|
||||
Guid tenantId,
|
||||
ReplacePlatformPrimaryDomainDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return platformAdminService.ReplacePrimaryDomainAsync(ResolveActor(), request.ToCommand(tenantId),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPost("tenants/{tenantId:guid}/owner-activation-links")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("一次性领取租户 Owner 激活链接")]
|
||||
[EndpointDescription("仅在主域名和试用/订阅有效时签发;幂等重放不会再次返回明文链接。")]
|
||||
public Task<PlatformOwnerActivationLinkResult> IssueOwnerActivationLink(
|
||||
Guid tenantId,
|
||||
IssuePlatformOwnerActivationLinkDto request,
|
||||
[FromHeader(Name = "Idempotency-Key")] [Required]
|
||||
string idempotencyKey,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return platformAdminService.IssueOwnerActivationLinkAsync(
|
||||
ResolveActor(), request.ToCommand(tenantId, idempotencyKey), cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("tenants/{tenantId:guid}/billing-policy")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("查询租户收款策略")]
|
||||
public Task<TenantBillingPolicyItem> GetBillingPolicy(Guid tenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
return platformAdminService.GetTenantBillingPolicyAsync(ResolveActor(), tenantId, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPut("tenants/{tenantId:guid}/billing-policy")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("更新租户收款策略")]
|
||||
public Task<TenantBillingPolicyItem> UpsertBillingPolicy(
|
||||
Guid tenantId,
|
||||
UpsertTenantBillingPolicyDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return platformAdminService.UpsertTenantBillingPolicyAsync(ResolveActor(), request.ToCommand(tenantId),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("tenants/detail")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("查询平台租户详情")]
|
||||
[ProducesResponseType<PlatformTenantDetail>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformTenantDetail>> TenantDetail(
|
||||
[FromQuery] Guid tenantId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetTenantDetailAsync(ResolveActor(), tenantId, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPatch("tenants/status")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("更新租户业务状态")]
|
||||
[PlatformOperationRisk("critical", PlatformApprovalPolicyCodes.TenantArchive)]
|
||||
[ProducesResponseType<PlatformCommandSubmission>(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType<PlatformCommandSubmission>(StatusCodes.Status202Accepted)]
|
||||
public async Task<ActionResult<PlatformCommandSubmission>> TenantStatus(
|
||||
UpdatePlatformTenantStatusDto request,
|
||||
[FromHeader(Name = "Idempotency-Key")] [Required]
|
||||
string idempotencyKey,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await approvalService.UpdateTenantStatusAsync(ResolveActor(), request.ToCommand(), idempotencyKey,
|
||||
cancellationToken);
|
||||
return result.ExecutionStatus == "pending_approval" ? Accepted(result) : Ok(result);
|
||||
}
|
||||
|
||||
[HttpPut("tenants/billing-profile")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("保存租户账务与开票资料")]
|
||||
[ProducesResponseType<TenantBillingProfileItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantBillingProfileItem>> BillingProfile(
|
||||
UpsertPlatformTenantBillingProfileDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.UpsertTenantBillingProfileAsync(ResolveActor(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("domains")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("查询租户域名状态")]
|
||||
[ProducesResponseType<PlatformDomainList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformDomainList>> Domains(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetDomainsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("domains/{domainId:guid}/recheck")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("重新触发租户域名 DNS/TLS 验证")]
|
||||
[ProducesResponseType<PlatformDomainRecheckResult>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformDomainRecheckResult>> RecheckDomain(
|
||||
Guid domainId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.RecheckDomainAsync(ResolveActor(), domainId, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("staff")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
|
||||
[EndpointSummary("查询平台员工列表")]
|
||||
[ProducesResponseType<PlatformStaffList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformStaffList>> Staff(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetStaffAsync(ResolveActor(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("staff")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
|
||||
[EndpointSummary("创建或更新平台员工")]
|
||||
[ProducesResponseType<PlatformStaffItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformStaffItem>> UpsertStaff(
|
||||
UpsertPlatformStaffDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.UpsertStaffAsync(ResolveActor(), request.ToCommand(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPatch("staff/status")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
|
||||
[EndpointSummary("启用或禁用平台员工")]
|
||||
[ProducesResponseType<PlatformStaffItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformStaffItem>> StaffStatus(
|
||||
UpdatePlatformStaffStatusDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.UpdateStaffStatusAsync(ResolveActor(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("staff/{userId:guid}/password-reset")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
|
||||
[EndpointSummary("为平台员工设置一次性临时密码")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> ResetStaffPassword(
|
||||
Guid userId,
|
||||
AdministrativePasswordResetDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var actor = ResolveActor();
|
||||
await authAdministrationService.ResetPasswordAsync(
|
||||
new AdministrativePasswordResetRequest(
|
||||
actor.UserId,
|
||||
userId,
|
||||
null,
|
||||
request.TemporaryPassword,
|
||||
request.Reason),
|
||||
cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpGet("audit-logs")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
|
||||
[EndpointSummary("查询平台审计日志")]
|
||||
[ProducesResponseType<PlatformAuditLogList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformAuditLogList>> AuditLogs(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetAuditLogsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("audit-alerts")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
|
||||
[EndpointSummary("查询平台审计告警")]
|
||||
[ProducesResponseType<PlatformAuditAlertList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformAuditAlertList>> AuditAlerts(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetAuditAlertsAsync(ResolveActor(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("audit-alerts/status")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
|
||||
[EndpointSummary("更新平台审计告警状态")]
|
||||
[ProducesResponseType<PlatformAuditAlert>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformAuditAlert>> AuditAlertStatus(
|
||||
UpdatePlatformAuditAlertStatusDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.UpdateAuditAlertStatusAsync(ResolveActor(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("saas/dunning/channels")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("查询平台催缴通知渠道")]
|
||||
[ProducesResponseType<PlatformBillingDunningChannelList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningChannelList>> BillingDunningChannels(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetBillingDunningChannelsAsync(ResolveActor(), query.ToQuery(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("saas/dunning/channels")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("创建或更新平台催缴通知渠道")]
|
||||
[ProducesResponseType<PlatformBillingDunningChannelItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningChannelItem>> UpsertBillingDunningChannel(
|
||||
UpsertPlatformBillingDunningChannelDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.UpsertBillingDunningChannelAsync(ResolveActor(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("saas/dunning/channels/disable")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("禁用平台催缴通知渠道")]
|
||||
[ProducesResponseType<PlatformBillingDunningChannelItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningChannelItem>> DisableBillingDunningChannel(
|
||||
DisablePlatformBillingDunningChannelDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.DisableBillingDunningChannelAsync(ResolveActor(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("saas/dunning/events")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("查询平台催缴通知事件")]
|
||||
[ProducesResponseType<PlatformBillingDunningEventList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventList>> BillingDunningEvents(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetBillingDunningEventsAsync(ResolveActor(), query.ToQuery(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("saas/dunning/events/detail")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("查询平台催缴通知事件详情")]
|
||||
[ProducesResponseType<PlatformBillingDunningEventItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventItem>> BillingDunningEventDetail(
|
||||
[FromQuery] Guid eventId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.GetBillingDunningEventDetailAsync(ResolveActor(), eventId,
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("saas/dunning/events/retry")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("重新标记平台催缴通知事件待发送")]
|
||||
[ProducesResponseType<PlatformBillingDunningEventItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventItem>> RetryBillingDunningEvent(
|
||||
RetryPlatformBillingDunningEventDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.RetryBillingDunningEventAsync(ResolveActor(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("saas/dunning/events/acknowledge")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("人工确认平台催缴通知事件")]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventItem>> AcknowledgeBillingDunningEvent(
|
||||
ResolvePlatformBillingDunningEventDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.AcknowledgeBillingDunningEventAsync(ResolveActor(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("saas/dunning/events/ignore")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("人工忽略平台催缴通知事件")]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventItem>> IgnoreBillingDunningEvent(
|
||||
ResolvePlatformBillingDunningEventDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await platformAdminService.IgnoreBillingDunningEventAsync(ResolveActor(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
private PlatformAdminActor ResolveActor()
|
||||
{
|
||||
if (currentUser.UserId is not { } userId)
|
||||
throw new PlatformAdminException("Platform admin actor was not resolved.", "platform_access_denied");
|
||||
|
||||
return new PlatformAdminActor(userId);
|
||||
}
|
||||
}
|
||||
55
Tiku.Api/Controllers/PlatformAuditAlertController.cs
Normal file
55
Tiku.Api/Controllers/PlatformAuditAlertController.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Tiku.Api.Contracts;
|
||||
using Tiku.Api.OpenApi;
|
||||
using Tiku.Application.Auth;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Tags("平台端-平台管理")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformDashboardView)]
|
||||
[Produces("application/json")]
|
||||
[Route("api/platform")]
|
||||
public sealed class PlatformAuditAlertController(
|
||||
IPlatformAuditAlertService service,
|
||||
PlatformAdminActorResolver actorResolver) : ControllerBase
|
||||
{
|
||||
[HttpGet("audit-logs")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
|
||||
[EndpointSummary("查询平台审计日志")]
|
||||
[ProducesResponseType<PlatformAuditLogList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformAuditLogList>> AuditLogs(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetAuditLogsAsync(actorResolver.Resolve(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("audit-alerts")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
|
||||
[EndpointSummary("查询平台审计告警")]
|
||||
[ProducesResponseType<PlatformAuditAlertList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformAuditAlertList>> AuditAlerts(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetAuditAlertsAsync(actorResolver.Resolve(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("audit-alerts/status")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformAuditView)]
|
||||
[EndpointSummary("更新平台审计告警状态")]
|
||||
[ProducesResponseType<PlatformAuditAlert>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformAuditAlert>> AuditAlertStatus(
|
||||
UpdatePlatformAuditAlertStatusDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.UpdateAuditAlertStatusAsync(actorResolver.Resolve(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
}
|
||||
29
Tiku.Api/Controllers/PlatformDashboardController.cs
Normal file
29
Tiku.Api/Controllers/PlatformDashboardController.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Tiku.Api.Contracts;
|
||||
using Tiku.Api.OpenApi;
|
||||
using Tiku.Application.Auth;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Tags("平台端-平台管理")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformDashboardView)]
|
||||
[Produces("application/json")]
|
||||
[Route("api/platform")]
|
||||
public sealed class PlatformDashboardController(
|
||||
IPlatformDashboardService service,
|
||||
PlatformAdminActorResolver actorResolver) : ControllerBase
|
||||
{
|
||||
[HttpGet("overview")]
|
||||
[EndpointSummary("查询平台经营概览")]
|
||||
[ProducesResponseType<PlatformOverview>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformOverview>> Overview(CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetOverviewAsync(actorResolver.Resolve(), cancellationToken));
|
||||
}
|
||||
}
|
||||
115
Tiku.Api/Controllers/PlatformDunningController.cs
Normal file
115
Tiku.Api/Controllers/PlatformDunningController.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Tiku.Api.Contracts;
|
||||
using Tiku.Api.OpenApi;
|
||||
using Tiku.Application.Auth;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Tags("平台端-平台管理")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformDashboardView)]
|
||||
[Produces("application/json")]
|
||||
[Route("api/platform")]
|
||||
public sealed class PlatformDunningController(
|
||||
IPlatformDunningService service,
|
||||
PlatformAdminActorResolver actorResolver) : ControllerBase
|
||||
{
|
||||
[HttpGet("saas/dunning/channels")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("查询平台催缴通知渠道")]
|
||||
[ProducesResponseType<PlatformBillingDunningChannelList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningChannelList>> BillingDunningChannels(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetBillingDunningChannelsAsync(actorResolver.Resolve(), query.ToQuery(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("saas/dunning/channels")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("创建或更新平台催缴通知渠道")]
|
||||
[ProducesResponseType<PlatformBillingDunningChannelItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningChannelItem>> UpsertBillingDunningChannel(
|
||||
UpsertPlatformBillingDunningChannelDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.UpsertBillingDunningChannelAsync(actorResolver.Resolve(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("saas/dunning/channels/disable")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("禁用平台催缴通知渠道")]
|
||||
[ProducesResponseType<PlatformBillingDunningChannelItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningChannelItem>> DisableBillingDunningChannel(
|
||||
DisablePlatformBillingDunningChannelDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.DisableBillingDunningChannelAsync(actorResolver.Resolve(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("saas/dunning/events")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("查询平台催缴通知事件")]
|
||||
[ProducesResponseType<PlatformBillingDunningEventList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventList>> BillingDunningEvents(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetBillingDunningEventsAsync(actorResolver.Resolve(), query.ToQuery(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("saas/dunning/events/detail")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("查询平台催缴通知事件详情")]
|
||||
[ProducesResponseType<PlatformBillingDunningEventItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventItem>> BillingDunningEventDetail(
|
||||
[FromQuery] Guid eventId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetBillingDunningEventDetailAsync(actorResolver.Resolve(), eventId,
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("saas/dunning/events/retry")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("重新标记平台催缴通知事件待发送")]
|
||||
[ProducesResponseType<PlatformBillingDunningEventItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventItem>> RetryBillingDunningEvent(
|
||||
RetryPlatformBillingDunningEventDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.RetryBillingDunningEventAsync(actorResolver.Resolve(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("saas/dunning/events/acknowledge")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("人工确认平台催缴通知事件")]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventItem>> AcknowledgeBillingDunningEvent(
|
||||
ResolvePlatformBillingDunningEventDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.AcknowledgeBillingDunningEventAsync(actorResolver.Resolve(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("saas/dunning/events/ignore")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformBillingNotification)]
|
||||
[EndpointSummary("人工忽略平台催缴通知事件")]
|
||||
public async Task<ActionResult<PlatformBillingDunningEventItem>> IgnoreBillingDunningEvent(
|
||||
ResolvePlatformBillingDunningEventDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.IgnoreBillingDunningEventAsync(actorResolver.Resolve(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
}
|
||||
77
Tiku.Api/Controllers/PlatformStaffAccessController.cs
Normal file
77
Tiku.Api/Controllers/PlatformStaffAccessController.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Tiku.Api.Contracts;
|
||||
using Tiku.Api.OpenApi;
|
||||
using Tiku.Application.Auth;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Tags("平台端-平台管理")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformDashboardView)]
|
||||
[Produces("application/json")]
|
||||
[Route("api/platform")]
|
||||
public sealed class PlatformStaffAccessController(
|
||||
IPlatformStaffAccessService service,
|
||||
IAuthAdministrationService authAdministrationService,
|
||||
PlatformAdminActorResolver actorResolver) : ControllerBase
|
||||
{
|
||||
[HttpGet("staff")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
|
||||
[EndpointSummary("查询平台员工列表")]
|
||||
[ProducesResponseType<PlatformStaffList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformStaffList>> Staff(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetStaffAsync(actorResolver.Resolve(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("staff")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
|
||||
[EndpointSummary("创建或更新平台员工")]
|
||||
[ProducesResponseType<PlatformStaffItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformStaffItem>> UpsertStaff(
|
||||
UpsertPlatformStaffDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.UpsertStaffAsync(actorResolver.Resolve(), request.ToCommand(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPatch("staff/status")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
|
||||
[EndpointSummary("启用或禁用平台员工")]
|
||||
[ProducesResponseType<PlatformStaffItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformStaffItem>> StaffStatus(
|
||||
UpdatePlatformStaffStatusDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.UpdateStaffStatusAsync(actorResolver.Resolve(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("staff/{userId:guid}/password-reset")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformStaffManage)]
|
||||
[EndpointSummary("为平台员工设置一次性临时密码")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> ResetStaffPassword(
|
||||
Guid userId,
|
||||
AdministrativePasswordResetDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var actor = actorResolver.Resolve();
|
||||
await authAdministrationService.ResetPasswordAsync(
|
||||
new AdministrativePasswordResetRequest(
|
||||
actor.UserId,
|
||||
userId,
|
||||
null,
|
||||
request.TemporaryPassword,
|
||||
request.Reason),
|
||||
cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
43
Tiku.Api/Controllers/PlatformTenantDomainController.cs
Normal file
43
Tiku.Api/Controllers/PlatformTenantDomainController.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Tiku.Api.Contracts;
|
||||
using Tiku.Api.OpenApi;
|
||||
using Tiku.Application.Auth;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Tags("平台端-平台管理")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformDashboardView)]
|
||||
[Produces("application/json")]
|
||||
[Route("api/platform")]
|
||||
public sealed class PlatformTenantDomainController(
|
||||
IPlatformTenantDomainService service,
|
||||
PlatformAdminActorResolver actorResolver) : ControllerBase
|
||||
{
|
||||
[HttpGet("domains")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("查询租户域名状态")]
|
||||
[ProducesResponseType<PlatformDomainList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformDomainList>> Domains(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetDomainsAsync(actorResolver.Resolve(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("domains/{domainId:guid}/recheck")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("重新触发租户域名 DNS/TLS 验证")]
|
||||
[ProducesResponseType<PlatformDomainRecheckResult>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformDomainRecheckResult>> RecheckDomain(
|
||||
Guid domainId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.RecheckDomainAsync(actorResolver.Resolve(), domainId, cancellationToken));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Tiku.Api.Contracts;
|
||||
using Tiku.Api.OpenApi;
|
||||
using Tiku.Application.Auth;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Tags("平台端-平台管理")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformDashboardView)]
|
||||
[Produces("application/json")]
|
||||
[Route("api/platform")]
|
||||
public sealed class TenantProvisioningAdministrationController(
|
||||
ITenantProvisioningAdministrationService service,
|
||||
IPlatformApprovalService approvalService,
|
||||
PlatformAdminActorResolver actorResolver) : ControllerBase
|
||||
{
|
||||
[HttpGet("tenants")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("查询平台租户列表")]
|
||||
[ProducesResponseType<PlatformTenantList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformTenantList>> Tenants(
|
||||
[FromQuery] PlatformAdminQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetTenantsAsync(actorResolver.Resolve(), query.ToQuery(), cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("tenants")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("创建平台租户")]
|
||||
[ProducesResponseType<PlatformTenantProvisioningResult>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformTenantProvisioningResult>> CreateTenant(
|
||||
CreatePlatformTenantDto request,
|
||||
[FromHeader(Name = "Idempotency-Key")] [Required]
|
||||
string idempotencyKey,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.CreateTenantAsync(
|
||||
actorResolver.Resolve(),
|
||||
request.ToCommand(idempotencyKey),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("tenants/{tenantId:guid}/primary-domain")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("更正租户主域名")]
|
||||
public Task<PlatformTenantDomainItem> ReplacePrimaryDomain(
|
||||
Guid tenantId,
|
||||
ReplacePlatformPrimaryDomainDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return service.ReplacePrimaryDomainAsync(actorResolver.Resolve(), request.ToCommand(tenantId),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPost("tenants/{tenantId:guid}/owner-activation-links")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("一次性领取租户 Owner 激活链接")]
|
||||
[EndpointDescription("仅在主域名和试用/订阅有效时签发;幂等重放不会再次返回明文链接。")]
|
||||
public Task<PlatformOwnerActivationLinkResult> IssueOwnerActivationLink(
|
||||
Guid tenantId,
|
||||
IssuePlatformOwnerActivationLinkDto request,
|
||||
[FromHeader(Name = "Idempotency-Key")] [Required]
|
||||
string idempotencyKey,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return service.IssueOwnerActivationLinkAsync(
|
||||
actorResolver.Resolve(), request.ToCommand(tenantId, idempotencyKey), cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("tenants/{tenantId:guid}/billing-policy")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("查询租户收款策略")]
|
||||
public Task<TenantBillingPolicyItem> GetBillingPolicy(Guid tenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
return service.GetTenantBillingPolicyAsync(actorResolver.Resolve(), tenantId, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPut("tenants/{tenantId:guid}/billing-policy")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("更新租户收款策略")]
|
||||
public Task<TenantBillingPolicyItem> UpsertBillingPolicy(
|
||||
Guid tenantId,
|
||||
UpsertTenantBillingPolicyDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return service.UpsertTenantBillingPolicyAsync(actorResolver.Resolve(), request.ToCommand(tenantId),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("tenants/detail")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("查询平台租户详情")]
|
||||
[ProducesResponseType<PlatformTenantDetail>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PlatformTenantDetail>> TenantDetail(
|
||||
[FromQuery] Guid tenantId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.GetTenantDetailAsync(actorResolver.Resolve(), tenantId, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPatch("tenants/status")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("更新租户业务状态")]
|
||||
[PlatformOperationRisk("critical", PlatformApprovalPolicyCodes.TenantArchive)]
|
||||
[ProducesResponseType<PlatformCommandSubmission>(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType<PlatformCommandSubmission>(StatusCodes.Status202Accepted)]
|
||||
public async Task<ActionResult<PlatformCommandSubmission>> TenantStatus(
|
||||
UpdatePlatformTenantStatusDto request,
|
||||
[FromHeader(Name = "Idempotency-Key")] [Required]
|
||||
string idempotencyKey,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await approvalService.UpdateTenantStatusAsync(actorResolver.Resolve(), request.ToCommand(), idempotencyKey,
|
||||
cancellationToken);
|
||||
return result.ExecutionStatus == "pending_approval" ? Accepted(result) : Ok(result);
|
||||
}
|
||||
|
||||
[HttpPut("tenants/billing-profile")]
|
||||
[Authorize(Policy = BackendPermissions.PlatformTenantManage)]
|
||||
[EndpointSummary("保存租户账务与开票资料")]
|
||||
[ProducesResponseType<TenantBillingProfileItem>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantBillingProfileItem>> BillingProfile(
|
||||
UpsertPlatformTenantBillingProfileDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await service.UpsertTenantBillingProfileAsync(actorResolver.Resolve(), request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
}
|
||||
@@ -324,10 +324,15 @@ public sealed record RetryPlatformBillingDunningEventCommand(Guid EventId, strin
|
||||
|
||||
public sealed record ResolvePlatformBillingDunningEventCommand(Guid EventId, string Reason);
|
||||
|
||||
public interface IPlatformAdminService
|
||||
public interface IPlatformDashboardService
|
||||
{
|
||||
Task<PlatformOverview> GetOverviewAsync(PlatformAdminActor actor, CancellationToken cancellationToken = default);
|
||||
|
||||
}
|
||||
|
||||
public interface ITenantProvisioningAdministrationService
|
||||
{
|
||||
|
||||
Task<PlatformTenantList> GetTenantsAsync(PlatformAdminActor actor, PlatformAdminQuery query,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
@@ -355,12 +360,20 @@ public interface IPlatformAdminService
|
||||
Task<TenantBillingPolicyItem> UpsertTenantBillingPolicyAsync(PlatformAdminActor actor,
|
||||
UpsertTenantBillingPolicyCommand command, CancellationToken cancellationToken = default);
|
||||
|
||||
}
|
||||
|
||||
public interface IPlatformTenantDomainService
|
||||
{
|
||||
Task<PlatformDomainList> GetDomainsAsync(PlatformAdminActor actor, PlatformAdminQuery query,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<PlatformDomainRecheckResult> RecheckDomainAsync(PlatformAdminActor actor, Guid domainId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
}
|
||||
|
||||
public interface IPlatformStaffAccessService
|
||||
{
|
||||
Task<PlatformStaffList> GetStaffAsync(PlatformAdminActor actor, PlatformAdminQuery query,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
@@ -370,6 +383,10 @@ public interface IPlatformAdminService
|
||||
Task<PlatformStaffItem> UpdateStaffStatusAsync(PlatformAdminActor actor, UpdatePlatformStaffStatusCommand command,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
}
|
||||
|
||||
public interface IPlatformAuditAlertService
|
||||
{
|
||||
Task<PlatformAuditLogList> GetAuditLogsAsync(PlatformAdminActor actor, PlatformAdminQuery query,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
@@ -379,6 +396,10 @@ public interface IPlatformAdminService
|
||||
Task<PlatformAuditAlert> UpdateAuditAlertStatusAsync(PlatformAdminActor actor,
|
||||
UpdatePlatformAuditAlertStatusCommand command, CancellationToken cancellationToken = default);
|
||||
|
||||
}
|
||||
|
||||
public interface IPlatformDunningService
|
||||
{
|
||||
Task<PlatformBillingDunningChannelList> GetBillingDunningChannelsAsync(PlatformAdminActor actor,
|
||||
PlatformAdminQuery query, CancellationToken cancellationToken = default);
|
||||
|
||||
|
||||
@@ -14,7 +14,13 @@ internal static class PlatformModule
|
||||
{
|
||||
internal static IServiceCollection AddPlatformModule(this IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<IPlatformAdminService, PlatformAdminService>();
|
||||
services.AddScoped<PlatformAdministrationDependencies>();
|
||||
services.AddScoped<IPlatformDashboardService, PlatformDashboardService>();
|
||||
services.AddScoped<ITenantProvisioningAdministrationService, TenantProvisioningAdministrationService>();
|
||||
services.AddScoped<IPlatformTenantDomainService, PlatformTenantDomainService>();
|
||||
services.AddScoped<IPlatformStaffAccessService, PlatformStaffAccessService>();
|
||||
services.AddScoped<IPlatformAuditAlertService, PlatformAuditAlertService>();
|
||||
services.AddScoped<IPlatformDunningService, PlatformDunningService>();
|
||||
services.AddScoped<IBackgroundJobHandler, TenantExportJobHandler>();
|
||||
services.AddScoped<IPlatformOperationsQueryService, PlatformOperationsQueryService>();
|
||||
services.AddOptions<TenantProvisioningOptions>();
|
||||
|
||||
@@ -5,7 +5,8 @@ using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed partial class PlatformAdminService
|
||||
internal sealed class PlatformAuditAlertService(PlatformAdministrationDependencies dependencies)
|
||||
: PlatformAdministrationServiceBase(dependencies), IPlatformAuditAlertService
|
||||
{
|
||||
public async Task<PlatformAuditLogList> GetAuditLogsAsync(
|
||||
PlatformAdminActor actor,
|
||||
@@ -4,7 +4,8 @@ using Tiku.Application.Security;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed partial class PlatformAdminService
|
||||
internal sealed class PlatformDashboardService(PlatformAdministrationDependencies dependencies)
|
||||
: PlatformAdministrationServiceBase(dependencies), IPlatformDashboardService
|
||||
{
|
||||
public async Task<PlatformOverview> GetOverviewAsync(
|
||||
PlatformAdminActor actor,
|
||||
@@ -5,7 +5,8 @@ using Tiku.Domain.Platform;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed partial class PlatformAdminService
|
||||
internal sealed class PlatformDunningService(PlatformAdministrationDependencies dependencies)
|
||||
: PlatformAdministrationServiceBase(dependencies), IPlatformDunningService
|
||||
{
|
||||
public async Task<PlatformBillingDunningChannelList> GetBillingDunningChannelsAsync(
|
||||
PlatformAdminActor actor,
|
||||
@@ -15,9 +15,9 @@ using Tiku.Infrastructure.Tenancy;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed partial class PlatformAdminService
|
||||
internal abstract partial class PlatformAdministrationServiceBase
|
||||
{
|
||||
private async Task AssertPlatformPermissionAsync(
|
||||
protected async Task AssertPlatformPermissionAsync(
|
||||
PlatformAdminActor actor,
|
||||
string permissionCode,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -27,7 +27,7 @@ internal sealed partial class PlatformAdminService
|
||||
throw new PlatformAdminException("Platform admin access is required.", "platform_access_denied");
|
||||
}
|
||||
|
||||
private static bool IsPlatformOperationIdempotencyConflict(DbUpdateException exception)
|
||||
protected static bool IsPlatformOperationIdempotencyConflict(DbUpdateException exception)
|
||||
{
|
||||
return exception.InnerException is PostgresException
|
||||
{
|
||||
@@ -38,7 +38,7 @@ internal sealed partial class PlatformAdminService
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private async Task<PlatformTenantProvisioningResult> ProvisioningReplayResultAsync(
|
||||
protected async Task<PlatformTenantProvisioningResult> ProvisioningReplayResultAsync(
|
||||
TikuDbContext dbContext,
|
||||
Guid tenantId,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -65,7 +65,7 @@ internal sealed partial class PlatformAdminService
|
||||
true);
|
||||
}
|
||||
|
||||
private static async Task<PlatformOwnerActivationLinkResult> OwnerActivationReplayResultAsync(
|
||||
protected static async Task<PlatformOwnerActivationLinkResult> OwnerActivationReplayResultAsync(
|
||||
TikuDbContext dbContext,
|
||||
Guid activationId,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -75,7 +75,7 @@ internal sealed partial class PlatformAdminService
|
||||
return new PlatformOwnerActivationLinkResult(grant.Id, null, grant.ExpiresAt, true);
|
||||
}
|
||||
|
||||
private async Task<PlatformOwnerActivationStatus> OwnerActivationStatusAsync(
|
||||
protected async Task<PlatformOwnerActivationStatus> OwnerActivationStatusAsync(
|
||||
TikuDbContext dbContext,
|
||||
Tenant tenant,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -101,7 +101,7 @@ internal sealed partial class PlatformAdminService
|
||||
return new PlatformOwnerActivationStatus(domainActive ? "ready_to_issue" : "domain_pending", null, null);
|
||||
}
|
||||
|
||||
private Task<TResult> ExecuteSystemAsync<TResult>(
|
||||
protected Task<TResult> ExecuteSystemAsync<TResult>(
|
||||
string reason,
|
||||
Func<TikuDbContext, Task<TResult>> operation,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -109,7 +109,7 @@ internal sealed partial class PlatformAdminService
|
||||
return ExecuteSystemAsync(reason, (_, dbContext) => operation(dbContext), cancellationToken);
|
||||
}
|
||||
|
||||
private Task<TResult> ExecuteSystemAsync<TResult>(
|
||||
protected Task<TResult> ExecuteSystemAsync<TResult>(
|
||||
string reason,
|
||||
Func<IServiceProvider, TikuDbContext, Task<TResult>> operation,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -118,7 +118,7 @@ internal sealed partial class PlatformAdminService
|
||||
new SystemScopeRequest(
|
||||
null,
|
||||
SystemScopeCallerType.Platform,
|
||||
nameof(PlatformAdminService),
|
||||
nameof(PlatformAdministrationServiceBase),
|
||||
reason,
|
||||
Guid.NewGuid().ToString("N"),
|
||||
true),
|
||||
@@ -126,7 +126,7 @@ internal sealed partial class PlatformAdminService
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private static async Task RequireTenantAsync(TikuDbContext dbContext, Guid tenantId,
|
||||
protected static async Task RequireTenantAsync(TikuDbContext dbContext, Guid tenantId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var exists =
|
||||
@@ -135,7 +135,7 @@ internal sealed partial class PlatformAdminService
|
||||
if (!exists) throw new PlatformAdminException("Tenant was not found.", "tenant_not_found");
|
||||
}
|
||||
|
||||
private static void AddAudit(TikuDbContext dbContext, PlatformAdminActor actor, string action, Guid targetId,
|
||||
protected static void AddAudit(TikuDbContext dbContext, PlatformAdminActor actor, string action, Guid targetId,
|
||||
object details)
|
||||
{
|
||||
dbContext.AuditLogs.Add(new AuditLog
|
||||
@@ -148,7 +148,7 @@ internal sealed partial class PlatformAdminService
|
||||
});
|
||||
}
|
||||
|
||||
private static PlatformTenantItem ToTenantItem(Tenant tenant, int domainCount,
|
||||
protected static PlatformTenantItem ToTenantItem(Tenant tenant, int domainCount,
|
||||
DateTimeOffset? subscriptionExpiresAt)
|
||||
{
|
||||
return new PlatformTenantItem(
|
||||
@@ -165,7 +165,7 @@ internal sealed partial class PlatformAdminService
|
||||
tenant.UpdatedAt);
|
||||
}
|
||||
|
||||
private static PlatformTenantDomainItem ToDomainItem(TenantDomain domain)
|
||||
protected static PlatformTenantDomainItem ToDomainItem(TenantDomain domain)
|
||||
{
|
||||
return new PlatformTenantDomainItem(
|
||||
domain.Id,
|
||||
@@ -184,7 +184,7 @@ internal sealed partial class PlatformAdminService
|
||||
null);
|
||||
}
|
||||
|
||||
private PlatformTenantDomainItem ToDomainItemWithInstructions(TenantDomain domain)
|
||||
protected PlatformTenantDomainItem ToDomainItemWithInstructions(TenantDomain domain)
|
||||
{
|
||||
return ToDomainItem(domain) with
|
||||
{
|
||||
@@ -194,7 +194,7 @@ internal sealed partial class PlatformAdminService
|
||||
};
|
||||
}
|
||||
|
||||
private static PlatformTenantSubscriptionItem ToSubscriptionItem(TenantSaasSubscription subscription)
|
||||
protected static PlatformTenantSubscriptionItem ToSubscriptionItem(TenantSaasSubscription subscription)
|
||||
{
|
||||
return new PlatformTenantSubscriptionItem(
|
||||
subscription.Id,
|
||||
@@ -208,7 +208,7 @@ internal sealed partial class PlatformAdminService
|
||||
subscription.Metadata);
|
||||
}
|
||||
|
||||
private static TenantBillingProfileItem ToBillingProfileItem(TenantBillingProfile profile)
|
||||
protected static TenantBillingProfileItem ToBillingProfileItem(TenantBillingProfile profile)
|
||||
{
|
||||
return new TenantBillingProfileItem(
|
||||
profile.TenantId,
|
||||
@@ -225,7 +225,7 @@ internal sealed partial class PlatformAdminService
|
||||
profile.Metadata);
|
||||
}
|
||||
|
||||
private static TenantBillingPolicyItem ToBillingPolicyItem(TenantBillingPolicy policy)
|
||||
protected static TenantBillingPolicyItem ToBillingPolicyItem(TenantBillingPolicy policy)
|
||||
{
|
||||
return new TenantBillingPolicyItem(
|
||||
policy.TenantId,
|
||||
@@ -237,7 +237,7 @@ internal sealed partial class PlatformAdminService
|
||||
policy.UpdatedAt);
|
||||
}
|
||||
|
||||
private static PlatformBillingDunningChannelItem ToDunningChannelItem(
|
||||
protected static PlatformBillingDunningChannelItem ToDunningChannelItem(
|
||||
PlatformBillingDunningNotificationChannel channel)
|
||||
{
|
||||
return new PlatformBillingDunningChannelItem(
|
||||
@@ -259,7 +259,7 @@ internal sealed partial class PlatformAdminService
|
||||
channel.UpdatedAt);
|
||||
}
|
||||
|
||||
private static PlatformBillingDunningEventItem ToDunningEventItem(PlatformBillingDunningNotificationEvent item)
|
||||
protected static PlatformBillingDunningEventItem ToDunningEventItem(PlatformBillingDunningNotificationEvent item)
|
||||
{
|
||||
return new PlatformBillingDunningEventItem(
|
||||
item.Id,
|
||||
@@ -283,7 +283,7 @@ internal sealed partial class PlatformAdminService
|
||||
item.UpdatedAt);
|
||||
}
|
||||
|
||||
private static PlatformStaffItem ToStaffItem(User user, IReadOnlyCollection<string> roleCodes)
|
||||
protected static PlatformStaffItem ToStaffItem(User user, IReadOnlyCollection<string> roleCodes)
|
||||
{
|
||||
return new PlatformStaffItem(
|
||||
user.Id,
|
||||
@@ -296,29 +296,29 @@ internal sealed partial class PlatformAdminService
|
||||
user.UpdatedAt);
|
||||
}
|
||||
|
||||
private static int Limit(int? limit)
|
||||
protected static int Limit(int? limit)
|
||||
{
|
||||
return Math.Clamp(limit ?? 50, 1, 200);
|
||||
}
|
||||
|
||||
private static string NormalizeCode(string value)
|
||||
protected static string NormalizeCode(string value)
|
||||
{
|
||||
return value.Trim().ToLowerInvariant();
|
||||
}
|
||||
|
||||
private static string? Normalize(string? value)
|
||||
protected static string? Normalize(string? value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
||||
}
|
||||
|
||||
private static string Required(string? value, string name)
|
||||
protected static string Required(string? value, string name)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value)
|
||||
? throw new PlatformAdminException($"{name} is required.", "idempotency_key_required")
|
||||
: value.Trim();
|
||||
}
|
||||
|
||||
private static string ProvisioningRequestHash(CreatePlatformTenantCommand command)
|
||||
protected static string ProvisioningRequestHash(CreatePlatformTenantCommand command)
|
||||
{
|
||||
var payload = JsonSerializer.Serialize(new
|
||||
{
|
||||
@@ -342,7 +342,7 @@ internal sealed partial class PlatformAdminService
|
||||
return Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(payload))).ToLowerInvariant();
|
||||
}
|
||||
|
||||
private static string OwnerActivationRequestHash(IssuePlatformOwnerActivationLinkCommand command)
|
||||
protected static string OwnerActivationRequestHash(IssuePlatformOwnerActivationLinkCommand command)
|
||||
{
|
||||
var payload = JsonSerializer.Serialize(new
|
||||
{
|
||||
@@ -353,7 +353,7 @@ internal sealed partial class PlatformAdminService
|
||||
return Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(payload))).ToLowerInvariant();
|
||||
}
|
||||
|
||||
private static TenantDomain CreatePrimaryDomain(Guid tenantId, string host)
|
||||
protected static TenantDomain CreatePrimaryDomain(Guid tenantId, string host)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -365,22 +365,22 @@ internal sealed partial class PlatformAdminService
|
||||
}
|
||||
}
|
||||
|
||||
private static string Base64Url(byte[] value)
|
||||
protected static string Base64Url(byte[] value)
|
||||
{
|
||||
return Convert.ToBase64String(value).TrimEnd('=').Replace('+', '-').Replace('/', '_');
|
||||
}
|
||||
|
||||
private string BuildOwnerActivationUrl(string host, Guid activationId, string token)
|
||||
protected string BuildOwnerActivationUrl(string host, Guid activationId, string token)
|
||||
{
|
||||
return TenantOwnerActivationUrlPolicy.Build(provisioning, host, activationId, token);
|
||||
}
|
||||
|
||||
private static JsonElement JsonObjectOrDefault(JsonElement value)
|
||||
protected static JsonElement JsonObjectOrDefault(JsonElement value)
|
||||
{
|
||||
return value.ValueKind == JsonValueKind.Object ? value.Clone() : JsonDocument.Parse("{}").RootElement.Clone();
|
||||
}
|
||||
|
||||
private static string? MaskPhone(string? phone)
|
||||
protected static string? MaskPhone(string? phone)
|
||||
{
|
||||
var value = Normalize(phone);
|
||||
return value is { Length: >= 7 }
|
||||
@@ -388,7 +388,7 @@ internal sealed partial class PlatformAdminService
|
||||
: value;
|
||||
}
|
||||
|
||||
private static string? MaskBankAccount(string? account)
|
||||
protected static string? MaskBankAccount(string? account)
|
||||
{
|
||||
var value = Normalize(account);
|
||||
return value is { Length: > 8 }
|
||||
@@ -396,7 +396,7 @@ internal sealed partial class PlatformAdminService
|
||||
: value;
|
||||
}
|
||||
|
||||
private static string MaskWebhook(string webhookUrl)
|
||||
protected static string MaskWebhook(string webhookUrl)
|
||||
{
|
||||
var value = Normalize(webhookUrl) ?? string.Empty;
|
||||
if (!Uri.TryCreate(value, UriKind.Absolute, out var uri))
|
||||
@@ -405,7 +405,7 @@ internal sealed partial class PlatformAdminService
|
||||
return $"{uri.Scheme}://{uri.Host}/****";
|
||||
}
|
||||
|
||||
private static string[] NormalizeArray(IReadOnlyCollection<string> values, string[] fallback)
|
||||
protected static string[] NormalizeArray(IReadOnlyCollection<string> values, string[] fallback)
|
||||
{
|
||||
var normalized = values
|
||||
.Select(Normalize)
|
||||
@@ -416,7 +416,7 @@ internal sealed partial class PlatformAdminService
|
||||
return normalized.Length == 0 ? fallback : normalized;
|
||||
}
|
||||
|
||||
private static bool ParseEnabledStatus(string status)
|
||||
protected static bool ParseEnabledStatus(string status)
|
||||
{
|
||||
return NormalizeCode(status) switch
|
||||
{
|
||||
@@ -426,17 +426,17 @@ internal sealed partial class PlatformAdminService
|
||||
};
|
||||
}
|
||||
|
||||
private static TenantStatus ParseTenantStatus(string status)
|
||||
protected static TenantStatus ParseTenantStatus(string status)
|
||||
{
|
||||
return Enum.TryParse<TenantStatus>(status, true, out var value) ? value : throw InvalidStatus(status);
|
||||
}
|
||||
|
||||
private static TenantDomainStatus ParseDomainStatus(string status)
|
||||
protected static TenantDomainStatus ParseDomainStatus(string status)
|
||||
{
|
||||
return Enum.TryParse<TenantDomainStatus>(status, true, out var value) ? value : throw InvalidStatus(status);
|
||||
}
|
||||
|
||||
private static async Task EnsureTenantOwnerRoleAsync(
|
||||
protected static async Task EnsureTenantOwnerRoleAsync(
|
||||
TikuDbContext dbContext,
|
||||
Guid tenantId,
|
||||
Guid ownerUserId,
|
||||
@@ -519,21 +519,21 @@ internal sealed partial class PlatformAdminService
|
||||
});
|
||||
}
|
||||
|
||||
private static PlatformAuditAlertStatus ParseAuditAlertStatus(string status)
|
||||
protected static PlatformAuditAlertStatus ParseAuditAlertStatus(string status)
|
||||
{
|
||||
return Enum.TryParse<PlatformAuditAlertStatus>(status, true, out var value)
|
||||
? value
|
||||
: throw InvalidStatus(status);
|
||||
}
|
||||
|
||||
private static PlatformBillingDunningNotificationStatus ParseDunningEventStatus(string status)
|
||||
protected static PlatformBillingDunningNotificationStatus ParseDunningEventStatus(string status)
|
||||
{
|
||||
return Enum.TryParse<PlatformBillingDunningNotificationStatus>(status, true, out var value)
|
||||
? value
|
||||
: throw InvalidStatus(status);
|
||||
}
|
||||
|
||||
private static PlatformAdminException InvalidStatus(string status)
|
||||
protected static PlatformAdminException InvalidStatus(string status)
|
||||
{
|
||||
return new PlatformAdminException($"Unsupported status '{status}'.", "invalid_status");
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Application.Tenancy;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed record PlatformAdministrationDependencies(
|
||||
ICurrentAccessContext CurrentAccessContext,
|
||||
ITenantExecutionScope TenantExecutionScope,
|
||||
IOptions<TenantProvisioningOptions> ProvisioningOptions,
|
||||
IOptions<DomainLifecycleOptions> DomainOptions);
|
||||
|
||||
internal abstract partial class PlatformAdministrationServiceBase(PlatformAdministrationDependencies dependencies)
|
||||
{
|
||||
protected ICurrentAccessContext currentAccessContext { get; } = dependencies.CurrentAccessContext;
|
||||
protected ITenantExecutionScope tenantExecutionScope { get; } = dependencies.TenantExecutionScope;
|
||||
protected DomainLifecycleOptions domains { get; } = dependencies.DomainOptions.Value;
|
||||
protected TenantProvisioningOptions provisioning { get; } = dependencies.ProvisioningOptions.Value;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Tiku.Application.PlatformAdmin;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Application.Tenancy;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed partial class PlatformAdminService(
|
||||
ICurrentAccessContext currentAccessContext,
|
||||
ITenantExecutionScope tenantExecutionScope,
|
||||
IOptions<TenantProvisioningOptions> provisioningOptions,
|
||||
IOptions<DomainLifecycleOptions> domainOptions) : IPlatformAdminService
|
||||
{
|
||||
private readonly DomainLifecycleOptions domains = domainOptions.Value;
|
||||
private readonly TenantProvisioningOptions provisioning = provisioningOptions.Value;
|
||||
}
|
||||
@@ -22,7 +22,7 @@ internal sealed class PlatformApprovalService(
|
||||
ITenantExecutionScope tenantExecutionScope,
|
||||
IOperationAuditService auditService,
|
||||
IPlatformBillingAdminService billingService,
|
||||
IPlatformAdminService platformAdminService,
|
||||
ITenantProvisioningAdministrationService tenantProvisioningService,
|
||||
IPlatformPaymentSettingsService paymentSettingsService,
|
||||
IBackofficeService backofficeService) : IPlatformApprovalService
|
||||
{
|
||||
@@ -177,11 +177,11 @@ internal sealed class PlatformApprovalService(
|
||||
{
|
||||
if (command.Status != TenantStatus.Archived)
|
||||
return ExecuteImmediateAsync(() =>
|
||||
platformAdminService.UpdateTenantStatusAsync(actor, command, cancellationToken));
|
||||
tenantProvisioningService.UpdateTenantStatusAsync(actor, command, cancellationToken));
|
||||
return SubmitAsync(actor.UserId, PlatformApprovalPolicyCodes.TenantArchive,
|
||||
nameof(UpdatePlatformTenantStatusCommand), "tenants", command.TenantId.ToString("N"), null,
|
||||
idempotencyKey, command.Reason, command,
|
||||
async token => await platformAdminService.UpdateTenantStatusAsync(actor, command, token),
|
||||
async token => await tenantProvisioningService.UpdateTenantStatusAsync(actor, command, token),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ internal sealed class PlatformApprovalService(
|
||||
.ConfirmManualPaymentAsync(new SaasCatalogActor(item.RequestedBy),
|
||||
Deserialize<ConfirmManualPaymentCommand>(item), cancellationToken),
|
||||
nameof(UpdatePlatformTenantStatusCommand) => await scope.ServiceProvider
|
||||
.GetRequiredService<IPlatformAdminService>()
|
||||
.GetRequiredService<ITenantProvisioningAdministrationService>()
|
||||
.UpdateTenantStatusAsync(new PlatformAdminActor(item.RequestedBy),
|
||||
Deserialize<UpdatePlatformTenantStatusCommand>(item), cancellationToken),
|
||||
nameof(UpsertPlatformPaymentChannelCommand) => await scope.ServiceProvider
|
||||
|
||||
@@ -8,7 +8,8 @@ using Tiku.Domain.Tenancy;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed partial class PlatformAdminService
|
||||
internal sealed class PlatformStaffAccessService(PlatformAdministrationDependencies dependencies)
|
||||
: PlatformAdministrationServiceBase(dependencies), IPlatformStaffAccessService
|
||||
{
|
||||
public async Task<PlatformStaffList> GetStaffAsync(
|
||||
PlatformAdminActor actor,
|
||||
@@ -7,7 +7,8 @@ using Tiku.Domain.Tenancy;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed partial class PlatformAdminService
|
||||
internal sealed class PlatformTenantDomainService(PlatformAdministrationDependencies dependencies)
|
||||
: PlatformAdministrationServiceBase(dependencies), IPlatformTenantDomainService
|
||||
{
|
||||
public async Task<PlatformDomainList> GetDomainsAsync(
|
||||
PlatformAdminActor actor,
|
||||
@@ -13,7 +13,8 @@ using Tiku.Infrastructure.Tenancy;
|
||||
|
||||
namespace Tiku.Infrastructure.PlatformAdmin;
|
||||
|
||||
internal sealed partial class PlatformAdminService
|
||||
internal sealed class TenantProvisioningAdministrationService(PlatformAdministrationDependencies dependencies)
|
||||
: PlatformAdministrationServiceBase(dependencies), ITenantProvisioningAdministrationService
|
||||
{
|
||||
public async Task<PlatformTenantList> GetTenantsAsync(
|
||||
PlatformAdminActor actor,
|
||||
@@ -35,7 +35,6 @@ public sealed class ArchitectureBoundaryTests
|
||||
var root = FindRepositoryRoot();
|
||||
var legacyLineBudgets = new Dictionary<string, int>(StringComparer.Ordinal)
|
||||
{
|
||||
["PlatformAdminService"] = 1719,
|
||||
["ContentManagementService"] = 1096,
|
||||
["PlatformQuestionBankService"] = 1033,
|
||||
["CommerceService"] = 983,
|
||||
|
||||
Reference in New Issue
Block a user