using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using API.Constants; using API.Data; using API.Data.Repositories; using API.DTOs.Dashboard; using API.DTOs.Filtering.v2; using API.Entities; using API.Extensions; using API.Helpers; using API.Services; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace API.Controllers; #nullable enable /// /// This is responsible for Filter caching /// public class FilterController : BaseApiController { private readonly IUnitOfWork _unitOfWork; private readonly ILocalizationService _localizationService; private readonly IStreamService _streamService; private readonly ILogger _logger; public FilterController(IUnitOfWork unitOfWork, ILocalizationService localizationService, IStreamService streamService, ILogger logger) { _unitOfWork = unitOfWork; _localizationService = localizationService; _streamService = streamService; _logger = logger; } /// /// Creates or Updates the filter /// /// /// [HttpPost("update")] public async Task CreateOrUpdateSmartFilter(FilterV2Dto dto) { var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId(), AppUserIncludes.SmartFilters); if (user == null) return Unauthorized(); if (User.IsInRole(PolicyConstants.ReadOnlyRole)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "permission-denied")); if (string.IsNullOrWhiteSpace(dto.Name)) return BadRequest("Name must be set"); if (Seed.DefaultStreams.Any(s => s.Name.Equals(dto.Name, StringComparison.InvariantCultureIgnoreCase))) { return BadRequest("You cannot use the name of a system provided stream"); } var existingFilter = user.SmartFilters.FirstOrDefault(f => f.Name.Equals(dto.Name, StringComparison.InvariantCultureIgnoreCase)); if (existingFilter != null) { // Update the filter existingFilter.Filter = SmartFilterHelper.Encode(dto); _unitOfWork.AppUserSmartFilterRepository.Update(existingFilter); } else { existingFilter = new AppUserSmartFilter() { Name = dto.Name, Filter = SmartFilterHelper.Encode(dto) }; user.SmartFilters.Add(existingFilter); _unitOfWork.UserRepository.Update(user); } if (!_unitOfWork.HasChanges()) return Ok(); await _unitOfWork.CommitAsync(); return Ok(); } [HttpGet] public ActionResult> GetFilters() { return Ok(_unitOfWork.AppUserSmartFilterRepository.GetAllDtosByUserId(User.GetUserId())); } [HttpDelete] public async Task DeleteFilter(int filterId) { if (User.IsInRole(PolicyConstants.ReadOnlyRole)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "permission-denied")); var filter = await _unitOfWork.AppUserSmartFilterRepository.GetById(filterId); if (filter == null) return Ok(); // This needs to delete any dashboard filters that have it too var streams = await _unitOfWork.UserRepository.GetDashboardStreamWithFilter(filter.Id); _unitOfWork.UserRepository.Delete(streams); var streams2 = await _unitOfWork.UserRepository.GetSideNavStreamWithFilter(filter.Id); _unitOfWork.UserRepository.Delete(streams2); _unitOfWork.AppUserSmartFilterRepository.Delete(filter); await _unitOfWork.CommitAsync(); return Ok(); } /// /// Encode the Filter /// /// /// [HttpPost("encode")] public ActionResult EncodeFilter(FilterV2Dto dto) { return Ok(SmartFilterHelper.Encode(dto)); } /// /// Decodes the Filter /// /// /// [HttpPost("decode")] public ActionResult DecodeFilter(DecodeFilterDto dto) { return Ok(SmartFilterHelper.Decode(dto.EncodedFilter)); } /// /// Rename a Smart Filter given the filterId and new name /// /// /// /// [HttpPost("rename")] public async Task RenameFilter([FromQuery] int filterId, [FromQuery] string name) { try { var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId(), AppUserIncludes.SmartFilters); if (user == null) return Unauthorized(); name = name.Trim(); if (User.IsInRole(PolicyConstants.ReadOnlyRole)) { return BadRequest(await _localizationService.Translate(user.Id, "permission-denied")); } if (string.IsNullOrWhiteSpace(name)) { return BadRequest(await _localizationService.Translate(user.Id, "smart-filter-name-required")); } if (Seed.DefaultStreams.Any(s => s.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))) { return BadRequest(await _localizationService.Translate(user.Id, "smart-filter-system-name")); } var filter = user.SmartFilters.FirstOrDefault(f => f.Id == filterId); if (filter == null) { return BadRequest(await _localizationService.Translate(user.Id, "filter-not-found")); } filter.Name = name; _unitOfWork.AppUserSmartFilterRepository.Update(filter); await _unitOfWork.CommitAsync(); await _streamService.RenameSmartFilterStreams(filter); return Ok(); } catch (Exception ex) { _logger.LogError(ex, "There was an exception when renaming smart filter: {FilterId}", filterId); return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-error")); } } }