using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Tiku.Api.Contracts; using Tiku.Api.OpenApi; using Tiku.Application.PlatformAdmin; using Tiku.Application.Security; using Tiku.Domain.Platform; namespace Tiku.Api.Controllers; [ApiController] [Tags("平台端-治理配置")] [Route("api/platform-admin/governance")] [Authorize(Policy = TikuPolicies.PlatformBackofficeBootstrap)] public sealed class PlatformGovernanceController( IPlatformGovernanceService governanceService, ICurrentAccessContext currentAccessContext) : ControllerBase { [HttpGet("configuration/definitions")] [Authorize(Policy = BackendPermissions.PlatformConfigurationManage)] [EndpointSummary("查询类型化平台配置定义")] public async Task> ConfigurationDefinitions(CancellationToken cancellationToken) => await governanceService.GetConfigurationDefinitionsAsync(await ActorAsync(cancellationToken), cancellationToken); [HttpGet("configuration/versions")] [Authorize(Policy = BackendPermissions.PlatformConfigurationManage)] [EndpointSummary("查询平台配置版本")] public async Task> ConfigurationVersions(string definitionCode, string? environment, CancellationToken cancellationToken) => await governanceService.GetConfigurationVersionsAsync(await ActorAsync(cancellationToken), definitionCode, environment, cancellationToken); [HttpPost("configuration/drafts")] [Authorize(Policy = BackendPermissions.PlatformConfigurationManage)] [EndpointSummary("保存平台配置草稿")] public async Task SaveConfigurationDraft(SavePlatformConfigurationDraftDto request, CancellationToken cancellationToken) => await governanceService.SaveConfigurationDraftAsync(await ActorAsync(cancellationToken), request.ToCommand(), cancellationToken); [HttpPost("configuration/versions/{versionId:guid}/publish")] [Authorize(Policy = BackendPermissions.PlatformConfigurationManage)] [EndpointSummary("发布平台配置版本")] [PlatformOperationRisk("high")] public async Task PublishConfiguration(Guid versionId, CancellationToken cancellationToken) => await governanceService.PublishConfigurationAsync(await ActorAsync(cancellationToken), versionId, cancellationToken); [HttpPost("configuration/versions/{versionId:guid}/rollback")] [Authorize(Policy = BackendPermissions.PlatformConfigurationManage)] [EndpointSummary("回滚平台配置版本")] [PlatformOperationRisk("high")] public async Task RollbackConfiguration(Guid versionId, PlatformRollbackDto request, CancellationToken cancellationToken) => await governanceService.RollbackConfigurationAsync(await ActorAsync(cancellationToken), versionId, request.Reason, cancellationToken); [HttpGet("notifications/templates")] [Authorize(Policy = BackendPermissions.PlatformNotificationManage)] [EndpointSummary("查询平台通知模板")] public async Task> NotificationTemplates(CancellationToken cancellationToken) => await governanceService.GetNotificationTemplatesAsync(await ActorAsync(cancellationToken), cancellationToken); [HttpPut("notifications/templates")] [Authorize(Policy = BackendPermissions.PlatformNotificationManage)] [EndpointSummary("新增或更新平台通知模板")] public async Task UpsertNotificationTemplate(UpsertPlatformNotificationTemplateDto request, CancellationToken cancellationToken) => await governanceService.UpsertNotificationTemplateAsync(await ActorAsync(cancellationToken), request.ToCommand(), cancellationToken); [HttpPost("notifications/send")] [Authorize(Policy = BackendPermissions.PlatformNotificationManage)] [EndpointSummary("按平台岗位发送通知")] public async Task> SendNotification(SendPlatformNotificationDto request, CancellationToken cancellationToken) => await governanceService.SendNotificationAsync(await ActorAsync(cancellationToken), request.ToCommand(), cancellationToken); [HttpGet("notifications/deliveries")] [Authorize(Policy = BackendPermissions.PlatformNotificationManage)] [EndpointSummary("分页查询平台通知投递")] public async Task> NotificationDeliveries( int page = 1, int pageSize = 50, string? search = null, PlatformNotificationDeliveryStatus? status = null, CancellationToken cancellationToken = default) => await governanceService.GetNotificationDeliveriesAsync(await ActorAsync(cancellationToken), new PagedQuery(page, pageSize, search), status, cancellationToken); [HttpPost("notifications/deliveries/{deliveryId:guid}/retry")] [Authorize(Policy = BackendPermissions.PlatformNotificationManage)] [EndpointSummary("重试平台通知投递")] public async Task RetryNotification(Guid deliveryId, CancellationToken cancellationToken) => await governanceService.RetryNotificationAsync(await ActorAsync(cancellationToken), deliveryId, cancellationToken); private async Task ActorAsync(CancellationToken cancellationToken) { var access = await currentAccessContext.GetAsync(cancellationToken); return access.UserId is { } userId && access.IsUserActive ? new PlatformApprovalActor(userId, access.PlatformPermissions) : throw new PlatformApprovalException("Platform actor was not resolved.", "platform_access_denied"); } }