using AutoMapper; using gehGassi.Core.Interfaces; using gehGassi.Core.Services; using gehGassi.Domain.Common; using gehGassi.Dto.Walks; using gehGassi.Dto; using gehGassi.Web.Helper; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using System.Threading.Tasks; using gehGassi.Dto.Ratings; using gehGassi.Domain.Walks; using gehGassi.Dto.Common; using System.Collections.Generic; using System; using gehGassi.Domain.Ratings; using gehGassi.Domain.Dogs; using System.Text.Json; using gehGassi.Web.Auth; using Asp.Versioning; namespace gehGassi.Web.Controllers.Api { /// /// Controller der die Verwaltung von Ratings via Api ermöglicht /// [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [ApiController] [ApiVersion(1)] [Route("api/ratings")] [Route("api/v{v:apiVersion}/ratings")] public class ApiRatingController : ApiBaseController { private readonly IRatingService _ratingService; /// /// Erstellt eine Instanz /// /// Instanz eines IMapper /// Instanz von LocalizationOptions /// Instanz eines IDogOwnerService /// Instanz eines IRatingService public ApiRatingController(IMapper mapper, IOptions localizationOptions, IAppUserService appUserService, IRatingService ratingService) : base(mapper, localizationOptions, appUserService) { _ratingService = ratingService; } /// /// Abfrage der Ratings eines AppUsers /// /// Id des AppUsers /// Letztes Update oder null, wenn noch keines /// Liste der Anfragen [HttpGet] [Route("GetRatingsForSync")] public async Task GetRatingsForSync(string appUserId, DateTimeOffset? lastUpdate) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { var ratings = await _ratingService.GetForSyncAppAsync(appUserId, lastUpdate); var dtoList = Mapper.Map>(ratings); return Ok(dtoList); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Anlegen eines Ratings /// /// RatingDto /// HTTP 200 OK, Felher sonst [HttpPost] [Route("CreateRating")] public async Task CreateRating(RatingDto model) { var clientOffset = GetClientDateOffset(); var result = new CreateResponseDto { Status = CreateStatusDto.Error, Value = null }; if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var existingRating = await _ratingService.GetAsync(model.Id); if (existingRating == null) { var rating = Mapper.Map(model); _ratingService.Add(rating); await _ratingService.CommitAsync(User.Identity.Name); await _ratingService.UpdateRatingStatisticsAsync(rating.TargetId, rating.TargetType); await _ratingService.CommitAsync(User.Identity.Name); result.Status = CreateStatusDto.Success; result.Value = Mapper.Map(rating); } else { result.Status = CreateStatusDto.Exists; } return Ok(result); } } return BadRequest(CommunicationErrors.Common_Model_Invalid); } /// /// Aktualisieren eines Ratings /// /// RatingDto /// HTTP 200 OK, Felher sonst [HttpPost] [Route("UpdateRating")] public async Task UpdateRating(RatingDto model) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var rating = await _ratingService.GetAsync(model.Id); if (rating != null) { if (model.UpdatedAt > rating.UpdatedAt) { Mapper.Map(model, rating); await _ratingService.CommitAsync(User.Identity.Name); await _ratingService.UpdateRatingStatisticsAsync(rating.TargetId, rating.TargetType); await _ratingService.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 Ratings /// /// RatingDto /// Id des App-Users /// 200OK [HttpPost] [Route("DeleteRating")] public async Task DeleteRating(RatingDto model, [FromQuery] string appUserId) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var rating = await _ratingService.GetAsync(model.Id); if (rating != null) { var appUser = await AppUserService.GetAsync(appUserId); if (appUser != null) { if (rating.FromId == appUser.Id) { //TODO: Löschen von verbundenen Daten! _ratingService.Remove(rating); await _ratingService.CommitAsync(User.Identity.Name); await _ratingService.UpdateRatingStatisticsAsync(rating.TargetId, rating.TargetType); await _ratingService.CommitAsync(User.Identity.Name); return Ok(); } } } return NotFound(CommunicationErrors.Common_NotFound); } return BadRequest(CommunicationErrors.Common_Model_Invalid); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Gibt ein Rating basierend auf Abfragekriterien zurück /// /// RatingCheckQueryDto /// HTTP 200 OK BOOL, Felher sonst [HttpPost] [Route("GetRatingEx")] public async Task GetRatingEx(RatingCheckQueryDto model) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var rating = await _ratingService.GetRatingExAsync(model.FromId, (AppUserType)model.FromType, model.TargetId, (RatingTarget)model.TargetType); if (rating != null) { var ratingDto = Mapper.Map(rating); return Ok(ratingDto); } else return NotFound(CommunicationErrors.Common_NotFound); } return BadRequest(CommunicationErrors.Common_Model_Invalid); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Prüft ob eine Bewertung bereits stattgefunden hat /// /// RatingCheckQueryDto /// HTTP 200 OK BOOL, Felher sonst [HttpPost] [Route("HasRated")] public async Task HasRated(RatingCheckQueryDto model) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var hasRated = await _ratingService.HasRatedAsync(model.FromId, (AppUserType)model.FromType, model.TargetId, (RatingTarget)model.TargetType); return Ok(hasRated); } return BadRequest(CommunicationErrors.Common_Model_Invalid); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Prüft ob eine Bewertung vorgenommen werden darf /// /// RatingCheckQueryDto /// HTTP 200 OK BOOL, Felher sonst [HttpPost] [Route("CanRate")] public async Task CanRate(RatingCheckQueryDto model) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var hasRated = await _ratingService.CanRateAsync(model.FromId, (AppUserType)model.FromType, model.TargetId, (RatingTarget)model.TargetType); return Ok(hasRated); } return BadRequest(CommunicationErrors.Common_Model_Invalid); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Abfragen von Ratings /// /// Abfragemodel /// Liste von Ratings [HttpPost] [Route("GetRatings")] public async Task GetRatings(RatingsQueryDto model) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { var baseAddress = GetBaseAddress(); var response = new ListResponseDto(); //Geodaten holen. //Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden //var (country, state) = await GetGeoDataAsync(model); var sortList = Mapper.Map>(model.DynamicSortOrder); var appUserId = User.AppUserId(); var queryResult = await _ratingService.GetWithNamesExAsync(appUserId, model.FromId, (AppUserType?)model.FromType, model.TargetId, (RatingTarget?)model.TargetType, sortList, model.Skip, model.Take); response.Total = queryResult.total; var resultList = queryResult.list; var dtoList = Mapper.Map>(resultList); foreach (var dtoItem in dtoList) { if(!string.IsNullOrWhiteSpace(dtoItem.FromPhoto)) dtoItem.FromPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.FromPhoto}"; if(!string.IsNullOrWhiteSpace(dtoItem.TargetPhoto)) dtoItem.TargetPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.TargetPhoto}"; } response.List = dtoList; response.Take = model.Take; response.Skip = model.Skip; return Ok(response); } return NotFound(CommunicationErrors.Common_NotFound); } /// /// Gibt ein Rating anhand der Id zurück /// /// Id der Bewertung /// 200 OK - Rating wenn gefunden, NOTFOUND sonst [HttpGet] [Route("GetRating")] public async Task GetRating(string ratingId) { var clientOffset = GetClientDateOffset(); if (User?.Identity != null && User.Identity.IsAuthenticated) { var baseAddress = GetBaseAddress(); var rating = await _ratingService.GetWithNamesAsync(ratingId); if (rating != null) { var ratingDto = Mapper.Map(rating); if (!string.IsNullOrWhiteSpace(ratingDto.FromPhoto)) ratingDto.FromPhoto = $"{baseAddress}/file/documents/thumbnails/{400}/{ratingDto.FromPhoto}"; if (!string.IsNullOrWhiteSpace(ratingDto.TargetPhoto)) ratingDto.TargetPhoto = $"{baseAddress}/file/documents/thumbnails/{400}/{ratingDto.TargetPhoto}"; return Ok(ratingDto); } } return NotFound(CommunicationErrors.Common_NotFound); } } }