< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.AssemblyListAccessKeysController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/AssemblyListAccessKeysController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 62
Coverable lines: 62
Total lines: 127
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 34
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%
Index()0%620%
Create()0%2040%
Create()0%812280%
Deactivate()100%210%
Activate()100%210%

File(s)

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

#LineLine coverage
 1using System.Security.Cryptography;
 2using System.Text.Json;
 3using Microsoft.AspNetCore.Authorization;
 4using Microsoft.AspNetCore.Mvc;
 5using Microsoft.EntityFrameworkCore;
 6using OzonDomains.Models;
 7using OzonRepositories.Context;
 8using Services.DataServices;
 9
 10namespace OzonOrdersWeb.Areas.Studio2.Controllers;
 11
 12[Authorize(Roles = "Admin")]
 13[Area("Studio2")]
 14public class AssemblyListAccessKeysController : Controller
 15{
 16    private readonly ApplicationDbContext _db;
 17    private readonly OzonClientServices _ozonClientServices;
 18
 019    public AssemblyListAccessKeysController(ApplicationDbContext db, OzonClientServices ozonClientServices)
 20    {
 021        _db = db;
 022        _ozonClientServices = ozonClientServices;
 023    }
 24
 25    [HttpGet]
 26    public async Task<IActionResult> Index()
 27    {
 028        var keys = await _db.AssemblyListAccessKeys
 029            .OrderByDescending(k => k.CreatedAt)
 030            .ToListAsync();
 031        var clients = await _ozonClientServices.GetOzonClients();
 032        ViewBag.Clients = clients;
 033        return View(keys);
 034    }
 35
 36    [HttpGet]
 37    public async Task<IActionResult> Create()
 38    {
 039        var clients = await _ozonClientServices.GetOzonClients();
 040        var warehouses = await _db.WarehouseMappings
 041            .Where(w => w.OzonWarehouseName != null && w.OzonWarehouseName != "")
 042            .Select(w => w.OzonWarehouseName)
 043            .Distinct()
 044            .OrderBy(w => w)
 045            .ToListAsync();
 046        ViewBag.Warehouses = warehouses.OfType<string>().ToList();
 047        ViewBag.Clients = clients;
 048        return View(new AssemblyListAccessKey());
 049    }
 50
 51    [HttpPost]
 52    [ValidateAntiForgeryToken]
 53    public async Task<IActionResult> Create(
 54        [Bind("Description,ExpiresAt,PeriodFromOffsetDays,PeriodToOffsetDays")] AssemblyListAccessKey model,
 55        [FromForm] List<int> allowedClientIds,
 56        [FromForm] List<string> allowedStatuses,
 57        [FromForm] List<string> allowedWarehouses)
 58    {
 59        // AccessKey — non-nullable string вне [Bind]-списка. Model binding валидирует ВСЮ модель
 60        // (включая неявный required для non-nullable reference type, т.к.
 61        // SuppressImplicitRequiredAttributeForNonNullableReferenceTypes не включён) ДО входа в тело
 62        // экшена, поэтому ModelState уже содержит ошибку "AccessKey field is required" на этом этапе —
 63        // простое присвоение значения ниже её не убирает, нужно явно снять запись из ModelState.
 064        ModelState.Remove(nameof(AssemblyListAccessKey.AccessKey));
 65
 066        model.AccessKey = Convert.ToHexString(RandomNumberGenerator.GetBytes(16)).ToLower();
 067        model.IsActive = true;
 068        model.CreatedAt = DateTime.UtcNow;
 069        model.AllowedOzonClientIds = JsonSerializer.Serialize(allowedClientIds ?? new List<int>());
 070        model.AllowedStatuses = JsonSerializer.Serialize(allowedStatuses ?? new List<string>());
 071        model.AllowedWarehouses = JsonSerializer.Serialize(allowedWarehouses ?? new List<string>());
 72
 073        if (allowedClientIds == null || allowedClientIds.Count == 0)
 074            ModelState.AddModelError(string.Empty, "Выберите хотя бы одного клиента Ozon.");
 75
 076        if (model.PeriodFromOffsetDays > model.PeriodToOffsetDays)
 077            ModelState.AddModelError(nameof(model.PeriodFromOffsetDays), "Дата «С» не может быть позже даты «По».");
 78
 079        if (model.PeriodFromOffsetDays < -365 || model.PeriodToOffsetDays > 365)
 080            ModelState.AddModelError(nameof(model.PeriodFromOffsetDays), "Смещение должно быть в пределах −365…+365 дней
 81
 082        if (!ModelState.IsValid)
 83        {
 84            // Дублируем все field-level ошибки в общую сводку (ModelOnly показывает только
 85            // string.Empty-ключи) — иначе пользователь не видит, почему форма не сохранилась.
 086            foreach (var entry in ModelState)
 87            {
 088                if (string.IsNullOrEmpty(entry.Key)) continue;
 089                foreach (var error in entry.Value.Errors)
 090                    ModelState.AddModelError(string.Empty, $"{entry.Key}: {error.ErrorMessage}");
 91            }
 92
 093            ViewBag.Clients = await _ozonClientServices.GetOzonClients();
 094            ViewBag.Warehouses = await _db.WarehouseMappings
 095                .Where(w => w.OzonWarehouseName != null && w.OzonWarehouseName != "")
 096                .Select(w => w.OzonWarehouseName)
 097                .Distinct()
 098                .OrderBy(w => w)
 099                .ToListAsync();
 0100            return View(model);
 101        }
 102
 0103        _db.AssemblyListAccessKeys.Add(model);
 0104        await _db.SaveChangesAsync();
 0105        return RedirectToAction(nameof(Index));
 0106    }
 107
 108    [HttpPost]
 109    [ValidateAntiForgeryToken]
 110    public async Task<IActionResult> Deactivate(long id)
 111    {
 0112        await _db.AssemblyListAccessKeys
 0113            .Where(k => k.Id == id)
 0114            .ExecuteUpdateAsync(s => s.SetProperty(k => k.IsActive, false));
 0115        return RedirectToAction(nameof(Index));
 0116    }
 117
 118    [HttpPost]
 119    [ValidateAntiForgeryToken]
 120    public async Task<IActionResult> Activate(long id)
 121    {
 0122        await _db.AssemblyListAccessKeys
 0123            .Where(k => k.Id == id)
 0124            .ExecuteUpdateAsync(s => s.SetProperty(k => k.IsActive, true));
 0125        return RedirectToAction(nameof(Index));
 0126    }
 127}