using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using RobotNet.MapManager.Data; using RobotNet.MapManager.Services; using RobotNet.MapShares; using RobotNet.MapShares.Dtos; using RobotNet.Shares; using System.Security.Cryptography; using System.Text; using System.Text.Json; namespace RobotNet.MapManager.Controllers; [Route("api/[controller]")] [ApiController] [Authorize] public class MapExportController(MapEditorDbContext MapDb, MapEditorStorageRepository StorageRepo, IHttpClientFactory HttpClientFactory, LoggerController Logger) : ControllerBase { private readonly byte[] Key = Encoding.UTF8.GetBytes("2512199802031998"); private readonly byte[] IV = Encoding.UTF8.GetBytes("2512199802031998"); [HttpGet] [Route("encrypt/{Id}")] public async Task EncryptMap(Guid Id) { try { var map = await MapDb.Maps.FirstOrDefaultAsync(m => m.Id == Id); if (map is null) return NotFound($"Map {Id} không tồn tại"); var (usingLocal, url) = StorageRepo.GetUrl("MapImages", $"{Id}"); byte[] imageData = await GetImageDataAsync(usingLocal, url); var elementModels = MapDb.ElementModels.Where(n => n.MapId == Id); List ElementModelExport = []; foreach (var elementModel in elementModels) { var getImageOpen = StorageRepo.GetUrl("ElementOpenModels", elementModel.Id.ToString()); byte[] imageElementModelOpenData = await GetImageDataAsync(getImageOpen.usingLocal, getImageOpen.url); var getImageClose = StorageRepo.GetUrl("ElementCloseModels", elementModel.Id.ToString()); byte[] imageElementModelCloseData = await GetImageDataAsync(getImageClose.usingLocal, getImageClose.url); ElementModelExport.Add(new ElementModelExportDto() { Id = elementModel.Id, Height = elementModel.Height, Width = elementModel.Width, Image1Height = elementModel.Image1Height, Image2Height = elementModel.Image2Height, Image1Width = elementModel.Image1Width, Image2Width = elementModel.Image2Width, Name = elementModel.Name, Content = elementModel.Content, ImageOpenData = imageElementModelOpenData, ImageCloseData = imageElementModelCloseData, }); } var nodes = MapDb.Nodes.Where(n => n.MapId == Id); var edges = MapDb.Edges.Where(n => n.MapId == Id); var zones = MapDb.Zones.Where(n => n.MapId == Id); var actions = MapDb.Actions.Where(n => n.MapId == Id); var elements = MapDb.Elements.Where(n => n.MapId == Id); var mapDto = new MapExportDto() { Id = Id, Name = map.Name, Description = map.Description, Info = new() { OriginX = map.OriginX, OriginY = map.OriginY, Resolution = map.Resolution, ViewX = map.ViewX, ViewY = map.ViewY, ViewWidth = map.ViewWidth, ViewHeight = map.ViewHeight, VDA5050 = map.VDA5050, }, Setting = new() { NodeNameAutoGenerate = map.NodeNameAutoGenerate, NodeNameTemplate = map.NodeNameTemplateDefault, NodeAllowedDeviationXy = map.EdgeAllowedDeviationXyDefault, NodeAllowedDeviationTheta = map.EdgeAllowedDeviationThetaDefault, EdgeStraightMaxSpeed = map.EdgeStraightMaxSpeedDefault, EdgeCurveMaxSpeed = map.EdgeCurveMaxSpeedDefault, EdgeMaxRotationSpeed = map.EdgeMaxRotationSpeedDefault, EdgeMinLength = map.EdgeMinLengthDefault, EdgeMaxHeight = map.EdgeMaxHeightDefault, EdgeMinHeight = map.EdgeMinHeightDefault, EdgeRotationAllowed = map.EdgeRotationAllowedDefault, EdgeDirectionAllowed = map.EdgeDirectionAllowedDefault, EdgeAllowedDeviationTheta = map.EdgeAllowedDeviationThetaDefault, EdgeAllowedDeviationXy = map.EdgeAllowedDeviationXyDefault, ZoneMinSquare = map.ZoneMinSquareDefault, }, Data = new() { NodeCount = map.NodeCount, Nodes = [.. nodes.Select(n => new NodeDto() { Id = n.Id, Name = n.Name, X = n.X, Y = n.Y, Theta = n.Theta, AllowedDeviationXy = n.AllowedDeviationXy, AllowedDeviationTheta = n.AllowedDeviationTheta, Actions = n.Actions, })], Edges = [.. edges.Select(e => new EdgeDto() { ControlPoint1X = e.ControlPoint1X, ControlPoint1Y = e.ControlPoint1Y, ControlPoint2X = e.ControlPoint2X, ControlPoint2Y = e.ControlPoint2Y, TrajectoryDegree = e.TrajectoryDegree, EndNodeId = e.EndNodeId, StartNodeId = e.StartNodeId, DirectionAllowed = e.DirectionAllowed, RotationAllowed = e.RotationAllowed, AllowedDeviationTheta = e.AllowedDeviationTheta, AllowedDeviationXy = e.AllowedDeviationXy, MaxHeight = e.MaxHeight, MinHeight = e.MinHeight, MaxSpeed = e.MaxSpeed, MaxRotationSpeed = e.MaxRotationSpeed, Actions = e.Actions, })], Zones = [.. zones.Select(z => new ZoneDto() { Type = z.Type, X1 = z.X1, Y1 = z.Y1, X2 = z.X2, Y2 = z.Y2, X3 = z.X3, Y3 = z.Y3, X4 = z.X4, Y4 = z.Y4, })], Actions = [.. actions.Select(a => new ActionDto() { Id = a.Id, Name = a.Name, Content = a.Content, })], ElementModels = [.. ElementModelExport], Elements = [.. elements.Select(e => new ElementDto() { Name = e.Name, IsOpen = e.IsOpen, ModelId = e.ModelId, NodeId = e.NodeId, OffsetX = e.OffsetX, OffsetY = e.OffsetY, Content = e.Content, })], ImageData = imageData, } }; var jsonData = JsonSerializer.Serialize(mapDto, JsonOptionExtends.Write); var data = EncryptDataAES(jsonData, Key, IV); return File(data, "application/octet-stream", $"{map.Name}.map"); } catch (Exception ex) { Logger.Warning($"EncryptMap: Hệ thống có lỗi xảy ra - {ex.Message}"); return NotFound("Hệ thống có lỗi xảy ra"); } } [HttpPost] [Route("decrypt")] public async Task> DecryptMap([FromForm(Name = "importmap")] IFormFile file) { try { if (file == null || file.Length == 0) return new(false, "File không hợp lệ"); if (!file.FileName.EndsWith(".map", StringComparison.OrdinalIgnoreCase)) return new(false, "Định dạng file không hợp lệ, yêu cầu file .map"); using var memoryStream = new MemoryStream(); await file.CopyToAsync(memoryStream); byte[] fileBytes = memoryStream.ToArray(); var jsonData = DecryptDataAES(fileBytes, Key, IV); var mapData = JsonSerializer.Deserialize(jsonData, JsonOptionExtends.Read); if (mapData is null) return new(false, "Dữ liệu không hợp lệ"); else return new(true) { Data = mapData }; } catch (Exception ex) { Logger.Warning($"EncryptMap: Hệ thống có lỗi xảy ra - {ex.Message}"); return new(false, $"EncryptMap: Hệ thống có lỗi xảy ra - {ex.Message}"); } } private static byte[] EncryptDataAES(string data, byte[] key, byte[] iv) { using Aes aesAlg = Aes.Create(); aesAlg.Key = key; aesAlg.IV = iv; ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); using MemoryStream msEncrypt = new(); using CryptoStream csEncrypt = new(msEncrypt, encryptor, CryptoStreamMode.Write); using (StreamWriter swEncrypt = new(csEncrypt)) { swEncrypt.Write(data); } return msEncrypt.ToArray(); } private static string DecryptDataAES(byte[] data, byte[] key, byte[] iv) { using Aes aesAlg = Aes.Create(); aesAlg.Key = key; aesAlg.IV = iv; ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); using MemoryStream msDecrypt = new(data); using CryptoStream csDecrypt = new(msDecrypt, decryptor, CryptoStreamMode.Read); using StreamReader srDecrypt = new(csDecrypt); return srDecrypt.ReadToEnd(); } public async Task GetImageDataAsync(bool usingLocal, string url) { if (!usingLocal) { var http = HttpClientFactory.CreateClient(); var response = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); if (!response.IsSuccessStatusCode) return []; return await response.Content.ReadAsByteArrayAsync(); } else { if (System.IO.File.Exists(url)) return System.IO.File.ReadAllBytes(url); return []; } } }