using System.Collections.Generic; using System.Threading.Tasks; using Kavita.API.Attributes; using Kavita.API.Database; using Kavita.API.Services; using Kavita.Models.Constants; using Kavita.Models.DTOs.Dashboard; using Kavita.Models.DTOs.SideNav; using Kavita.Server.Attributes; using Microsoft.AspNetCore.Mvc; namespace Kavita.Server.Controllers; /// /// Responsible for anything that deals with Streams (SmartFilters, ExternalSource, DashboardStream, SideNavStream) /// public class StreamController( IStreamService streamService, IUnitOfWork unitOfWork) : BaseApiController { /// /// Returns the layout of the user's dashboard /// /// [HttpGet("dashboard")] public async Task>> GetDashboardLayout(bool visibleOnly = true) { return Ok(await streamService.GetDashboardStreams(UserId, visibleOnly)); } /// /// Return's the user's side nav /// [HttpGet("sidenav")] public async Task>> GetSideNav(bool visibleOnly = true) { return Ok(await streamService.GetSidenavStreams(UserId, visibleOnly)); } /// /// Return's the user's external sources /// [HttpGet("external-sources")] public async Task>> GetExternalSources() { return Ok(await streamService.GetExternalSources(UserId)); } /// /// Create an external Source /// /// /// [HttpPost("create-external-source")] public async Task> CreateExternalSource(ExternalSourceDto dto) { // Check if a host and api key exists for the current user return Ok(await streamService.CreateExternalSource(UserId, dto)); } /// /// Updates an existing external source /// /// /// [HttpPost("update-external-source")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task> UpdateExternalSource(ExternalSourceDto dto) { // Check if a host and api key exists for the current user return Ok(await streamService.UpdateExternalSource(UserId, dto)); } /// /// Validates the external source by host is unique (for this user) /// /// /// [HttpPost("external-source-exists")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task> ExternalSourceExists(ExternalSourceDto dto) { return Ok(await unitOfWork.AppUserExternalSourceRepository.ExternalSourceExists(UserId, dto.Name, dto.Host, dto.ApiKey)); } /// /// Delete's the external source /// /// /// [HttpDelete("delete-external-source")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task ExternalSourceExists(int externalSourceId) { await streamService.DeleteExternalSource(UserId, externalSourceId); return Ok(); } /// /// Creates a Dashboard Stream from a SmartFilter and adds it to the user's dashboard as visible /// /// /// [HttpPost("add-dashboard-stream")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task> AddDashboard([FromQuery] int smartFilterId) { return Ok(await streamService.CreateDashboardStreamFromSmartFilter(UserId, smartFilterId)); } /// /// Updates the visibility of a dashboard stream /// /// /// [HttpPost("update-dashboard-stream")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task UpdateDashboardStream(DashboardStreamDto dto) { await streamService.UpdateDashboardStream(UserId, dto); return Ok(); } /// /// Updates the position of a dashboard stream /// /// /// [HttpPost("update-dashboard-position")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task UpdateDashboardStreamPosition(UpdateStreamPositionDto dto) { await streamService.UpdateDashboardStreamPosition(UserId, dto); return Ok(); } /// /// Creates a SideNav Stream from a SmartFilter and adds it to the user's sidenav as visible /// /// /// [HttpPost("add-sidenav-stream")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task> AddSideNav([FromQuery] int smartFilterId) { return Ok(await streamService.CreateSideNavStreamFromSmartFilter(UserId, smartFilterId)); } /// /// Creates a SideNav Stream from a SmartFilter and adds it to the user's sidenav as visible /// /// /// [HttpPost("add-sidenav-stream-from-external-source")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task> AddSideNavFromExternalSource([FromQuery] int externalSourceId) { return Ok(await streamService.CreateSideNavStreamFromExternalSource(UserId, externalSourceId)); } /// /// Updates the visibility of a dashboard stream /// /// /// [HttpPost("update-sidenav-stream")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task UpdateSideNavStream(SideNavStreamDto dto) { await streamService.UpdateSideNavStream(UserId, dto); return Ok(); } /// /// Updates the position of a dashboard stream /// /// /// [HttpPost("update-sidenav-position")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task UpdateSideNavStreamPosition(UpdateStreamPositionDto dto) { await streamService.UpdateSideNavStreamPosition(UserId, dto); return Ok(); } [HttpPost("bulk-sidenav-stream-visibility")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task BulkUpdateSideNavStream(BulkUpdateSideNavStreamVisibilityDto dto) { await streamService.UpdateSideNavStreamBulk(UserId, dto); return Ok(); } /// /// Removes a Smart Filter from a user's SideNav Streams /// /// /// [HttpDelete("smart-filter-side-nav-stream")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task DeleteSmartFilterSideNavStream([FromQuery] int sideNavStreamId) { await streamService.DeleteSideNavSmartFilterStream(UserId, sideNavStreamId); return Ok(); } /// /// Removes a Smart Filter from a user's Dashboard Streams /// /// /// [HttpDelete("smart-filter-dashboard-stream")] [DisallowRole(PolicyConstants.ReadOnlyRole)] public async Task DeleteSmartFilterDashboardStream([FromQuery] int dashboardStreamId) { await streamService.DeleteDashboardSmartFilterStream(UserId, dashboardStreamId); return Ok(); } }