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);
}
}