using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Security.Claims; using UniVerse.Application.DTOs.Common; using UniVerse.Application.DTOs.Notifications; using UniVerse.Application.Interfaces; namespace UniVerse.Api.Controllers; /// Отправка и планирование уведомлений через доступные каналы. [ApiController] [Route("api/v1/notifications")] [Authorize] [Produces("application/json")] public class NotificationsController : ControllerBase { private readonly INotificationService _notifications; public NotificationsController(INotificationService notifications) { _notifications = notifications; } private int CurrentUserId => int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub") ?? "0"); /// Получить уведомления текущего пользователя. /// Параметры пагинации. /// Токен отмены запроса. /// Список уведомлений. /// Требуется аутентификация. [HttpGet] [ProducesResponseType(typeof(PagedResult), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task>> GetMine( [FromQuery] PaginationRequest pagination, CancellationToken cancellationToken) => Ok(await _notifications.GetUserNotificationsAsync(CurrentUserId, pagination, cancellationToken)); /// Отметить все уведомления текущего пользователя как прочитанные. /// Токен отмены запроса. /// Уведомления отмечены прочитанными. /// Требуется аутентификация. [HttpPatch("read-all")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task MarkAllRead(CancellationToken cancellationToken) { await _notifications.MarkAllReadAsync(CurrentUserId, cancellationToken); return NoContent(); } /// Отправить уведомление немедленно. /// /// Канал задаётся строкой, например `email`. Новые провайдеры добавляются через `INotificationProvider`. /// /// Канал, получатель, тема и текст уведомления. /// Уведомление принято к отправке. /// Требуется аутентификация. /// Требуется роль Admin. [Authorize(Roles = "Admin")] [HttpPost("send")] [ProducesResponseType(StatusCodes.Status202Accepted)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task Send([FromBody] SendNotificationRequest request, CancellationToken cancellationToken) { var message = new NotificationMessage( request.Channel, request.Recipient, request.Subject, request.Body, request.RecipientName, request.Metadata); await _notifications.SendAsync(message, cancellationToken); return Accepted(); } /// Запланировать отложенную отправку уведомления через Quartz.NET. /// Уведомление и момент отправки. /// Уведомление поставлено в очередь Quartz.NET. /// Требуется аутентификация. /// Требуется роль Admin. [Authorize(Roles = "Admin")] [HttpPost("schedule")] [ProducesResponseType(typeof(ScheduledNotificationResponse), StatusCodes.Status202Accepted)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> Schedule([FromBody] ScheduleNotificationRequest request, CancellationToken cancellationToken) { var response = await _notifications.ScheduleAsync(request, cancellationToken); return Accepted(response); } }