using System.Security.Cryptography; using Microsoft.AspNetCore.Mvc; using Server.WatchBody.Core.Dal.Src.Domain; using Server.WatchBody.Core.Dal.Src.Repository; using Server.WatchBody.Web.Services; namespace Server.WatchBody.Web.Controllers.Admin; /// Атлеты (spec 02 m08): список/создание/смена ключа/блок. public class AdminAthletesController(AdminAuthService auth, IAthleteRepository athletes) : AdminControllerBase(auth) { public ActionResult List() { if (Denied()) return UnauthorizedJson(); var items = athletes.Select(null) .OrderBy(a => a.Id) .Select(a => new { a.Id, a.Name, a.IsBlocked, createdAt = a.CreatedAt, }); return new JsonResult(new { items }); } public ActionResult Create() { if (Denied()) return UnauthorizedJson(); var name = ReadString("name"); if (string.IsNullOrWhiteSpace(name)) return ErrorJson(400, "name пуст"); var (key, hash) = NewKey(); var id = athletes.Insert(new Athlete { Name = name, ApiKeyHash = hash }); // ключ возвращается один раз (🛡2): дальше в БД только хэш Response.StatusCode = 201; return new JsonResult(new { id, apiKey = key }); } public ActionResult NewKey(int id) { if (Denied()) return UnauthorizedJson(); var athlete = athletes.Get(id); if (athlete == null) return ErrorJson(404, "not_found"); var (key, hash) = NewKey(); athletes.Update(new Athlete { Id = id, Name = athlete.Name, ApiKeyHash = hash, IsBlocked = athlete.IsBlocked, }); return new JsonResult(new { apiKey = key }); } public ActionResult Block(int id) { if (Denied()) return UnauthorizedJson(); var athlete = athletes.Get(id); if (athlete == null) return ErrorJson(404, "not_found"); var blocked = ReadBool("isBlocked") ?? !athlete.IsBlocked; athletes.Update(new Athlete { Id = id, Name = athlete.Name, ApiKeyHash = athlete.ApiKeyHash, IsBlocked = blocked, }); return new JsonResult(new { id, isBlocked = blocked }); } private static (string Key, string Hash) NewKey() { var key = "wb-" + Convert.ToHexString(RandomNumberGenerator.GetBytes(12)).ToLowerInvariant(); return (key, Services.ApiKeyHash.Of(key)); } private string? ReadString(string property) { using var reader = new StreamReader(Request.Body); var json = reader.ReadToEndAsync().GetAwaiter().GetResult(); try { using var doc = System.Text.Json.JsonDocument.Parse(json); return doc.RootElement.TryGetProperty(property, out var value) ? value.GetString() : null; } catch (System.Text.Json.JsonException) { return null; } } private bool? ReadBool(string property) { using var reader = new StreamReader(Request.Body); var json = reader.ReadToEndAsync().GetAwaiter().GetResult(); try { using var doc = System.Text.Json.JsonDocument.Parse(json); return doc.RootElement.TryGetProperty(property, out var value) && value.ValueKind is System.Text.Json.JsonValueKind.True or System.Text.Json.JsonValueKind.False ? value.GetBoolean() : null; } catch (System.Text.Json.JsonException) { return null; } } }