using AutoMapper; using gehGassi.Core.Interfaces; using gehGassi.Core.Services; using gehGassi.Dto.News; using gehGassi.Dto; using gehGassi.Web.Helper; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Collections.Generic; using System.Threading.Tasks; using System; using gehGassi.Dto.Dogs; using gehGassi.Dto.Common; using gehGassi.Dto.Messages; using NuGet.Protocol.Plugins; using Microsoft.AspNetCore.Http; using System.IO; using gehGassi.Domain.Dogs; using gehGassi.Web.Auth; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Processing; using gehGassi.Web.Models; using Asp.Versioning; namespace gehGassi.Web.Controllers.Api { /// /// Controller der Zugriff auf Hunde und Hunderassen via API ermöglicht /// [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [ApiController] [ApiVersion(1)] [Route("api/dogs")] [Route("api/v{v:apiVersion}/dogs")] public class ApiDogsController : ApiBaseController { private readonly ILogger _logger; private readonly IDogRaceService _dogRaceService; private readonly IDogService _dogService; /// /// Erstellt eine Instanz /// /// Instanz eines IMapper /// Instanz eines ILogger /// Instanz von LocalizationOptions /// Instanz eines IAppUserService /// Instanz eines IDogRaceService /// Instanz eines IDogService public ApiDogsController(IMapper mapper, ILogger logger, IOptions localizationOptions, IAppUserService appUserService, IDogRaceService dogRaceService, IDogService dogService) : base(mapper, localizationOptions, appUserService) { _logger = logger; _dogRaceService = dogRaceService; _dogService = dogService; } /// /// Gibt eine Liste von Hunderassen für die Synchronisierung mit der App zurück /// /// Letztes Update oder null, wenn noch keines /// Gewünschte Sprache /// HTTP 200 wenn erfolgreich [Route("GetRaces")] [HttpGet] public async Task GetRaces(DateTimeOffset? lastUpdate, string language) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { var races = await _dogRaceService.GetForSyncAsync(lastUpdate, language, LocalizationOptions.Value.DefaultCulture); var racesDto = Mapper.Map>(races); return Ok(racesDto); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Gibt eine eine Hunderassen zurück /// /// Id der hunderasse /// Gewünschte Sprache /// HTTP 200 wenn erfolgreich [Route("GetRace")] [HttpGet] public async Task GetRace(string id, string language) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { var race = await _dogRaceService.GetWithNamesAsync(id, language, LocalizationOptions.Value.DefaultCulture); var raceDto = Mapper.Map(race); return Ok(raceDto); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Abfrage der Hunde eines AppUsers /// /// Id des AppUsers /// Letztes Update oder null, wenn noch keines /// Liste der Hunde [HttpGet] [Route("GetDogs")] public async Task GetDogs(string appUserId, DateTimeOffset? lastUpdate) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { var dogs = await _dogService.GetDogsAsync(appUserId, lastUpdate); var dogsDtoList = Mapper.Map>(dogs); var baseAddress = GetBaseAddress(); foreach (var item in dogsDtoList) { item.Photo = !string.IsNullOrWhiteSpace(item.Photo) ? $"{baseAddress}/file/documents/thumbnails/{400}/{item.Photo}" : ""; } return Ok(dogsDtoList); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Abfrage der Hunde eines AppUsers als DogMinInfo /// /// Id des Hundebesitzers /// Gewünschte Sprache /// Liste der Hunde als MinInfo [HttpGet] [Route("GetDogsMin")] public async Task GetDogsMin(string dogOwnerId, string language) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { var appUserId = User.AppUserId(); var locked = await AppUserService.IsLockedAsync(dogOwnerId); var blocked = await AppUserService.IsBlockedAsync(appUserId, dogOwnerId); var dogs = await _dogService.GetWithNamesOwnerAsync(dogOwnerId, language, LocalizationOptions.Value.DefaultCulture); var dogsDtoList = Mapper.Map>(dogs); var baseAddress = GetBaseAddress(); foreach (var item in dogsDtoList) { item.Photo = !string.IsNullOrWhiteSpace(item.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{item.Photo}" : ""; item.Locked = locked; item.Blocked = blocked; } return Ok(dogsDtoList); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Gibt einen hund zurück /// /// Id des Hundes /// Hunde [HttpGet] [Route("GetDog")] public async Task GetDog(string dogId) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { var dog = await _dogService.GetAsync(dogId); var dogDto = Mapper.Map(dog); var baseAddress = GetBaseAddress(); dogDto.Photo = !string.IsNullOrWhiteSpace(dogDto.Photo) ? $"{baseAddress}/file/documents/thumbnails/{400}/{dogDto.Photo}" : ""; var appUserId = User.AppUserId(); dogDto.Locked = await AppUserService.IsLockedAsync(dog.AppUserId); dogDto.Blocked = await AppUserService.IsBlockedAsync(appUserId, dog.AppUserId); return Ok(dogDto); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Anlegen eines Hundes /// /// DogDto /// Optional Foto /// CreateResponseDto [HttpPost] [Route("Add")] public async Task Add([ModelBinder(BinderType = typeof(JsonModelBinder))] DogDto model, IFormFile photoUpdateFile) { var clientOffset = GetClientDateOffset(); var result = new CreateResponseDto { Status = CreateStatusDto.Error, Value = null }; if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var dog = await _dogService.GetAsync(model.Id); if (dog == null) { dog = _dogService.Create(); Mapper.Map(model, dog); dog.Id = model.Id; //Da die Id schon in der App generiert wurde if (model.BirthDate.HasValue) dog.BirthDate = new DateTimeOffset(model.BirthDate.Value.DateTime, TimeSpan.Zero); dog.Number = await _dogService.GetNextNumberAsync(); try { if (photoUpdateFile != null && !string.IsNullOrEmpty(photoUpdateFile.FileName)) { var extension = Path.GetExtension(photoUpdateFile.FileName); var filenameToUse = FileServiceHelper.GetDogPath(dog.Id) + $"dog_{Guid.NewGuid():N}{extension}"; using var memoryStream = new MemoryStream(); await photoUpdateFile.CopyToAsync(memoryStream); memoryStream.Position = 0; using var img = await Image.LoadAsync(memoryStream); img.Mutate(x => x.Resize(new ResizeOptions() { Mode = ResizeMode.Crop, Size = new Size(800) })); var format = img.DetectEncoder(photoUpdateFile.FileName); await using var memStream = new MemoryStream(); await img.SaveAsync(memStream, format); memStream.Position = 0; await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, memStream); dog.Photo = filenameToUse; //Thumbnails erstellten await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); } } catch (Exception ex) { } _dogService.Add(dog); await _dogService.CommitAsync(User.Identity.Name); var dtoDog = Mapper.Map(dog); result.Status = CreateStatusDto.Success; result.Value = dtoDog; return Ok(result); } result.Status = CreateStatusDto.Exists; return Ok(result); } return BadRequest(CommunicationErrors.Common_Model_Invalid); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Aktualisieren eines Hundes /// /// DogDto /// Optional Foto /// 200OK [HttpPost] [Route("Update")] public async Task Update([ModelBinder(BinderType = typeof(JsonModelBinder))] DogDto model, IFormFile photoUpdateFile) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var dog = await _dogService.GetAsync(model.Id); if (dog != null) { if (model.UpdatedAt > dog.UpdatedAt) { var oldPhoto = dog.Photo; Mapper.Map(model, dog); if (string.IsNullOrWhiteSpace(model.Photo) || model.Photo.StartsWithHttp()) { //Altes Foto behalten wenn eines als Link kommt dog.Photo = oldPhoto; } try { if (photoUpdateFile != null && !string.IsNullOrEmpty(photoUpdateFile.FileName)) { //Wenn es ein altes Foto gibt, dieses löschen if (!string.IsNullOrWhiteSpace(oldPhoto)) { await FileService.DeleteAsync(FileServiceHelper.DocumentContainer, oldPhoto); await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldPhoto, 400); await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldPhoto, 200); await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldPhoto, 100); } var extension = Path.GetExtension(photoUpdateFile.FileName); var filenameToUse = FileServiceHelper.GetDogPath(dog.Id) + $"dog_{Guid.NewGuid():N}{extension}"; using var memoryStream = new MemoryStream(); await photoUpdateFile.CopyToAsync(memoryStream); memoryStream.Position = 0; using var img = await Image.LoadAsync(memoryStream); img.Mutate(x => x.Resize(new ResizeOptions() { Mode = ResizeMode.Crop, Size = new Size(800) })); var format = img.DetectEncoder(photoUpdateFile.FileName); await using var memStream = new MemoryStream(); await img.SaveAsync(memStream, format); memStream.Position = 0; await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, memStream); dog.Photo = filenameToUse; //Thumbnails erstellten await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); } } catch (Exception ex) { } await _dogService.CommitAsync(User.Identity.Name); } return Ok(); } return NotFound(CommunicationErrors.Common_NotFound); } return BadRequest(CommunicationErrors.Common_Model_Invalid); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Löschen eines Hundes /// /// DogDto /// Id des App-Users /// 200OK [HttpPost] [Route("Delete")] public async Task Delete([ModelBinder(BinderType = typeof(JsonModelBinder))] DogDto model, [FromQuery]string appUserId) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var dog = await _dogService.GetAsync(model.Id); if (dog != null) { var appUser = await AppUserService.GetAsync(appUserId); if (appUser != null) { if (dog.AppUserId == appUser.Id) { var postingPath = FileServiceHelper.GetDogPath(dog.Id); await FileService.ClearDirectoryAsync(FileServiceHelper.DocumentContainer, postingPath); await RemoveThumbnail(FileServiceHelper.DocumentContainer, dog.Photo, 400); await RemoveThumbnail(FileServiceHelper.DocumentContainer, dog.Photo, 200); await RemoveThumbnail(FileServiceHelper.DocumentContainer, dog.Photo, 100); _dogService.Remove(dog); await _dogService.CommitAsync(User.Identity.Name); return Ok(); } } } return NotFound(CommunicationErrors.Common_NotFound); } return BadRequest(CommunicationErrors.Common_Model_Invalid); } return NotFound(CommunicationErrors.Common_NotFound); } } }