< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.SystemNotificationController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/SystemNotificationController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 45
Coverable lines: 45
Total lines: 116
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 20
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
DeployEvent()0%110100%
SendNotification()0%110100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/SystemNotificationController.cs

#LineLine coverage
 1using Microsoft.AspNetCore.Mvc;
 2using Microsoft.Extensions.Configuration;
 3using OzonOrdersWeb.Authorization;
 4using Services.ApiServices.TelegramBotApi;
 5using Services.SignalRServices;
 6using System.Linq;
 7
 8namespace OzonOrdersWeb.Areas.Studio2.Controllers
 9{
 10    [Area("Studio2")]
 11    [ServiceEndpoint]
 12    public class SystemNotificationController : Controller
 13    {
 14        private readonly IConfiguration _configuration;
 15        private readonly ILogger<SystemNotificationController> _logger;
 16        private readonly ITelegramNotifier _telegram;
 17
 018        public SystemNotificationController(IConfiguration configuration, ILogger<SystemNotificationController> logger,
 019            ITelegramNotifier telegram)
 20        {
 021            _configuration = configuration;
 022            _logger = logger;
 023            _telegram = telegram;
 024        }
 25
 26        /// <summary>
 27        /// Принимает событие деплоя от GitHub Actions (началось / завершено / не удалось) и отправляет его в Telegram:
 28        /// версия, список изменений со ссылками на коммиты и PR. Ключ — в заголовке <c>X-Api-Key</c>
 29        /// (тот же <c>SystemNotification:ApiKey</c>), чтобы он не попадал в строку запроса и логи.
 30        /// </summary>
 31        [HttpPost]
 32        [IgnoreAntiforgeryToken]
 33        public async Task<IActionResult> DeployEvent([FromBody] DeployEvent? deployEvent, CancellationToken cancellation
 34        {
 035            var apiKey = _configuration["SystemNotification:ApiKey"];
 036            if (string.IsNullOrEmpty(apiKey))
 37            {
 038                _logger.LogInformation("SystemNotification:ApiKey не настроен — событие деплоя отклонено");
 039                return BadRequest(new { error = "Ключ безопасности не настроен" });
 40            }
 41
 042            var key = Request.Headers["X-Api-Key"].ToString();
 043            if (string.IsNullOrEmpty(key) || !System.Security.Cryptography.CryptographicOperations.FixedTimeEquals(
 044                    System.Text.Encoding.UTF8.GetBytes(key), System.Text.Encoding.UTF8.GetBytes(apiKey)))
 45            {
 046                _logger.LogInformation("Событие деплоя отклонено: неверный или отсутствующий ключ безопасности");
 047                return Unauthorized(new { error = "Неверный ключ безопасности" });
 48            }
 49
 050            if (deployEvent == null || string.IsNullOrWhiteSpace(deployEvent.Sha))
 051                return BadRequest(new { error = "Не указан sha" });
 52
 053            var sent = await _telegram.SendAsync(TelegramMessageFactory.Deploy(deployEvent), cancellationToken);
 054            _logger.LogInformation("Событие деплоя {Stage} {Sha}: Telegram={Sent}", deployEvent.Stage, deployEvent.Sha, 
 055            return Ok(new { success = true, telegram = sent });
 056        }
 57
 58        /// <summary>
 59        /// Отправляет системное уведомление всем активным пользователям через SignalR
 60        /// </summary>
 61        /// <param name="key">Ключ безопасности из appsettings.json</param>
 62        /// <param name="message">Текст сообщения для отправки</param>
 63        /// <param name="type">Тип уведомления: info, warning, danger, success (по умолчанию: info)</param>
 64        /// <returns></returns>
 65        [HttpGet]
 66        public async Task<IActionResult> SendNotification(string key, string message, string type = "info")
 67        {
 68            try
 69            {
 70                // Проверка ключа безопасности
 071                var apiKey = _configuration["SystemNotification:ApiKey"];
 072                if (string.IsNullOrEmpty(apiKey))
 73                {
 074                    _logger.LogInformation("SystemNotification:ApiKey не настроен в appsettings.json");
 075                    return BadRequest(new { error = "Ключ безопасности не настроен" });
 76                }
 77
 078                if (string.IsNullOrEmpty(key) || key != apiKey)
 79                {
 080                    _logger.LogInformation("Попытка отправки системного уведомления отклонена: неверный ключ безопасност
 081                    return Unauthorized(new { error = "Неверный ключ безопасности" });
 82                }
 83
 084                if (string.IsNullOrEmpty(message))
 85                {
 086                    return BadRequest(new { error = "Сообщение не может быть пустым" });
 87                }
 88
 89                // Валидация типа уведомления
 090                var validTypes = new[] { "info", "warning", "danger", "success" };
 091                if (!validTypes.Contains(type.ToLower()))
 92                {
 093                    type = "info";
 94                }
 95
 96                // Отправка системного уведомления через SignalR
 097                await NotificationService.NotifySystemAsync(message);
 98
 099                _logger.LogInformation("Системное уведомление отправлено всем пользователям: {Message}", message);
 100
 0101                return Ok(new
 0102                {
 0103                    success = true,
 0104                    message = "Уведомление успешно отправлено всем активным пользователям",
 0105                    sentAt = DateTime.Now
 0106                });
 107            }
 0108            catch (Exception ex)
 109            {
 0110                _logger.LogError(ex, "Ошибка при отправке системного уведомления");
 0111                return StatusCode(500, new { error = "Внутренняя ошибка сервера при отправке уведомления" });
 112            }
 0113        }
 114    }
 115}
 116