Merged develop into main
This commit is contained in:
commit
aa710529f0
151 changed files with 4393 additions and 1703 deletions
|
@ -7,10 +7,10 @@ using API.Constants;
|
|||
using API.DTOs;
|
||||
using API.DTOs.Account;
|
||||
using API.Entities;
|
||||
using API.Errors;
|
||||
using API.Extensions;
|
||||
using API.Interfaces;
|
||||
using API.Interfaces.Services;
|
||||
using API.Services;
|
||||
using AutoMapper;
|
||||
using Kavita.Common;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
@ -31,13 +31,14 @@ namespace API.Controllers
|
|||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly ILogger<AccountController> _logger;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IAccountService _accountService;
|
||||
|
||||
/// <inheritdoc />
|
||||
public AccountController(UserManager<AppUser> userManager,
|
||||
SignInManager<AppUser> signInManager,
|
||||
ITokenService tokenService, IUnitOfWork unitOfWork,
|
||||
ILogger<AccountController> logger,
|
||||
IMapper mapper)
|
||||
IMapper mapper, IAccountService accountService)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
|
@ -45,6 +46,7 @@ namespace API.Controllers
|
|||
_unitOfWork = unitOfWork;
|
||||
_logger = logger;
|
||||
_mapper = mapper;
|
||||
_accountService = accountService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -61,30 +63,10 @@ namespace API.Controllers
|
|||
if (resetPasswordDto.UserName != User.GetUsername() && !User.IsInRole(PolicyConstants.AdminRole))
|
||||
return Unauthorized("You are not permitted to this operation.");
|
||||
|
||||
// Validate Password
|
||||
foreach (var validator in _userManager.PasswordValidators)
|
||||
var errors = await _accountService.ChangeUserPassword(user, resetPasswordDto.Password);
|
||||
if (errors.Any())
|
||||
{
|
||||
var validationResult = await validator.ValidateAsync(_userManager, user, resetPasswordDto.Password);
|
||||
if (!validationResult.Succeeded)
|
||||
{
|
||||
return BadRequest(
|
||||
validationResult.Errors.Select(e => new ApiException(400, e.Code, e.Description)));
|
||||
}
|
||||
}
|
||||
|
||||
var result = await _userManager.RemovePasswordAsync(user);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
_logger.LogError("Could not update password");
|
||||
return BadRequest(result.Errors.Select(e => new ApiException(400, e.Code, e.Description)));
|
||||
}
|
||||
|
||||
|
||||
result = await _userManager.AddPasswordAsync(user, resetPasswordDto.Password);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
_logger.LogError("Could not update password");
|
||||
return BadRequest(result.Errors.Select(e => new ApiException(400, e.Code, e.Description)));
|
||||
return BadRequest(errors);
|
||||
}
|
||||
|
||||
_logger.LogInformation("{User}'s Password has been reset", resetPasswordDto.UserName);
|
||||
|
@ -110,6 +92,13 @@ namespace API.Controllers
|
|||
user.UserPreferences ??= new AppUserPreferences();
|
||||
user.ApiKey = HashUtil.ApiKey();
|
||||
|
||||
var settings = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
|
||||
if (!settings.EnableAuthentication && !registerDto.IsAdmin)
|
||||
{
|
||||
_logger.LogInformation("User {UserName} is being registered as non-admin with no server authentication. Using default password.", registerDto.Username);
|
||||
registerDto.Password = AccountService.DefaultPassword;
|
||||
}
|
||||
|
||||
var result = await _userManager.CreateAsync(user, registerDto.Password);
|
||||
|
||||
if (!result.Succeeded) return BadRequest(result.Errors);
|
||||
|
@ -166,6 +155,14 @@ namespace API.Controllers
|
|||
|
||||
if (user == null) return Unauthorized("Invalid username");
|
||||
|
||||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdmin(user);
|
||||
var settings = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
|
||||
if (!settings.EnableAuthentication && !isAdmin)
|
||||
{
|
||||
_logger.LogDebug("User {UserName} is logging in with authentication disabled", loginDto.Username);
|
||||
loginDto.Password = AccountService.DefaultPassword;
|
||||
}
|
||||
|
||||
var result = await _signInManager
|
||||
.CheckPasswordSignInAsync(user, loginDto.Password, false);
|
||||
|
||||
|
|
|
@ -2,13 +2,11 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Constants;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using API.Extensions;
|
||||
using API.Interfaces;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace API.Controllers
|
||||
|
@ -19,13 +17,11 @@ namespace API.Controllers
|
|||
public class CollectionController : BaseApiController
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly UserManager<AppUser> _userManager;
|
||||
|
||||
/// <inheritdoc />
|
||||
public CollectionController(IUnitOfWork unitOfWork, UserManager<AppUser> userManager)
|
||||
public CollectionController(IUnitOfWork unitOfWork)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -36,7 +32,7 @@ namespace API.Controllers
|
|||
public async Task<IEnumerable<CollectionTagDto>> GetAllTags()
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername());
|
||||
var isAdmin = await _userManager.IsInRoleAsync(user, PolicyConstants.AdminRole);
|
||||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdmin(user);
|
||||
if (isAdmin)
|
||||
{
|
||||
return await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync();
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace API.Controllers
|
|||
public async Task<ActionResult> DownloadVolume(int volumeId)
|
||||
{
|
||||
var files = await _unitOfWork.VolumeRepository.GetFilesForVolume(volumeId);
|
||||
var volume = await _unitOfWork.SeriesRepository.GetVolumeByIdAsync(volumeId);
|
||||
var volume = await _unitOfWork.VolumeRepository.GetVolumeByIdAsync(volumeId);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(volume.SeriesId);
|
||||
try
|
||||
{
|
||||
|
@ -92,7 +92,7 @@ namespace API.Controllers
|
|||
{
|
||||
var files = await _unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapterId);
|
||||
var chapter = await _unitOfWork.ChapterRepository.GetChapterAsync(chapterId);
|
||||
var volume = await _unitOfWork.SeriesRepository.GetVolumeByIdAsync(chapter.VolumeId);
|
||||
var volume = await _unitOfWork.VolumeRepository.GetVolumeByIdAsync(chapter.VolumeId);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(volume.SeriesId);
|
||||
try
|
||||
{
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using API.Extensions;
|
||||
using API.Interfaces;
|
||||
using API.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace API.Controllers
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data.Repositories;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
@ -179,7 +180,7 @@ namespace API.Controllers
|
|||
|
||||
try
|
||||
{
|
||||
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryId);
|
||||
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryId, LibraryIncludes.None);
|
||||
_unitOfWork.LibraryRepository.Delete(library);
|
||||
await _unitOfWork.CommitAsync();
|
||||
|
||||
|
@ -203,7 +204,7 @@ namespace API.Controllers
|
|||
[HttpPost("update")]
|
||||
public async Task<ActionResult> UpdateLibrary(UpdateLibraryDto libraryForUserDto)
|
||||
{
|
||||
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryForUserDto.Id);
|
||||
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryForUserDto.Id, LibraryIncludes.Folders);
|
||||
|
||||
var originalFolders = library.Folders.Select(x => x.Path).ToList();
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ using System.Linq;
|
|||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using API.Comparators;
|
||||
using API.Constants;
|
||||
using API.DTOs;
|
||||
using API.DTOs.Filtering;
|
||||
using API.DTOs.OPDS;
|
||||
|
@ -16,7 +15,6 @@ using API.Interfaces;
|
|||
using API.Interfaces.Services;
|
||||
using API.Services;
|
||||
using Kavita.Common;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace API.Controllers
|
||||
|
@ -26,7 +24,6 @@ namespace API.Controllers
|
|||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IDownloadService _downloadService;
|
||||
private readonly IDirectoryService _directoryService;
|
||||
private readonly UserManager<AppUser> _userManager;
|
||||
private readonly ICacheService _cacheService;
|
||||
private readonly IReaderService _readerService;
|
||||
|
||||
|
@ -41,13 +38,12 @@ namespace API.Controllers
|
|||
private readonly ChapterSortComparer _chapterSortComparer = new ChapterSortComparer();
|
||||
|
||||
public OpdsController(IUnitOfWork unitOfWork, IDownloadService downloadService,
|
||||
IDirectoryService directoryService, UserManager<AppUser> userManager,
|
||||
ICacheService cacheService, IReaderService readerService)
|
||||
IDirectoryService directoryService, ICacheService cacheService,
|
||||
IReaderService readerService)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_downloadService = downloadService;
|
||||
_directoryService = directoryService;
|
||||
_userManager = userManager;
|
||||
_cacheService = cacheService;
|
||||
_readerService = readerService;
|
||||
|
||||
|
@ -170,16 +166,16 @@ namespace API.Controllers
|
|||
return BadRequest("OPDS is not enabled on this server");
|
||||
var userId = await GetUser(apiKey);
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
|
||||
var isAdmin = await _userManager.IsInRoleAsync(user, PolicyConstants.AdminRole);
|
||||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdmin(user);
|
||||
|
||||
IEnumerable <CollectionTagDto> tags;
|
||||
IList<CollectionTagDto> tags;
|
||||
if (isAdmin)
|
||||
{
|
||||
tags = await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync();
|
||||
tags = (await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync()).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
tags = await _unitOfWork.CollectionTagRepository.GetAllPromotedTagDtosAsync();
|
||||
tags = (await _unitOfWork.CollectionTagRepository.GetAllPromotedTagDtosAsync()).ToList();
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,6 +197,14 @@ namespace API.Controllers
|
|||
});
|
||||
}
|
||||
|
||||
if (tags.Count == 0)
|
||||
{
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
{
|
||||
Title = "Nothing here",
|
||||
});
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
}
|
||||
|
||||
|
@ -213,7 +217,7 @@ namespace API.Controllers
|
|||
return BadRequest("OPDS is not enabled on this server");
|
||||
var userId = await GetUser(apiKey);
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
|
||||
var isAdmin = await _userManager.IsInRoleAsync(user, PolicyConstants.AdminRole);
|
||||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdmin(user);
|
||||
|
||||
IEnumerable <CollectionTagDto> tags;
|
||||
if (isAdmin)
|
||||
|
@ -300,13 +304,13 @@ namespace API.Controllers
|
|||
|
||||
var feed = CreateFeed(readingList.Title + " Reading List", $"{apiKey}/reading-list/{readingListId}", apiKey);
|
||||
|
||||
var items = await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId);
|
||||
var items = (await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId)).ToList();
|
||||
foreach (var item in items)
|
||||
{
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
{
|
||||
Id = item.ChapterId.ToString(),
|
||||
Title = "Chapter " + item.ChapterNumber,
|
||||
Title = $"{item.SeriesName} Chapter {item.ChapterNumber}",
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{item.SeriesId}/volume/{item.VolumeId}/chapter/{item.ChapterId}"),
|
||||
|
@ -315,6 +319,14 @@ namespace API.Controllers
|
|||
});
|
||||
}
|
||||
|
||||
if (items.Count == 0)
|
||||
{
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
{
|
||||
Title = "Nothing here",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -373,6 +385,14 @@ namespace API.Controllers
|
|||
feed.Entries.Add(CreateSeries(seriesDto, apiKey));
|
||||
}
|
||||
|
||||
if (recentlyAdded.Count == 0)
|
||||
{
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
{
|
||||
Title = "Nothing here",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
}
|
||||
|
@ -404,6 +424,14 @@ namespace API.Controllers
|
|||
feed.Entries.Add(CreateSeries(seriesDto, apiKey));
|
||||
}
|
||||
|
||||
if (pagedList.Count == 0)
|
||||
{
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
{
|
||||
Title = "Nothing here",
|
||||
});
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
}
|
||||
|
||||
|
@ -467,7 +495,7 @@ namespace API.Controllers
|
|||
return BadRequest("OPDS is not enabled on this server");
|
||||
var userId = await GetUser(apiKey);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||
var volumes = await _unitOfWork.SeriesRepository.GetVolumesDtoAsync(seriesId, userId);
|
||||
var volumes = await _unitOfWork.VolumeRepository.GetVolumesDtoAsync(seriesId, userId);
|
||||
var feed = CreateFeed(series.Name + " - Volumes", $"{apiKey}/series/{series.Id}", apiKey);
|
||||
feed.Links.Add(CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/series-cover?seriesId={seriesId}"));
|
||||
foreach (var volumeDto in volumes)
|
||||
|
@ -486,7 +514,7 @@ namespace API.Controllers
|
|||
return BadRequest("OPDS is not enabled on this server");
|
||||
var userId = await GetUser(apiKey);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||
var volume = await _unitOfWork.SeriesRepository.GetVolumeAsync(volumeId);
|
||||
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(volumeId);
|
||||
var chapters =
|
||||
(await _unitOfWork.ChapterRepository.GetChaptersAsync(volumeId)).OrderBy(x => double.Parse(x.Number),
|
||||
_chapterSortComparer);
|
||||
|
@ -517,7 +545,7 @@ namespace API.Controllers
|
|||
return BadRequest("OPDS is not enabled on this server");
|
||||
var userId = await GetUser(apiKey);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||
var volume = await _unitOfWork.SeriesRepository.GetVolumeAsync(volumeId);
|
||||
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(volumeId);
|
||||
var chapter = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(chapterId);
|
||||
var files = await _unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapterId);
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace API.Controllers
|
|||
public async Task<ActionResult> MarkRead(MarkReadDto markReadDto)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername(), AppUserIncludes.Progress);
|
||||
var volumes = await _unitOfWork.SeriesRepository.GetVolumes(markReadDto.SeriesId);
|
||||
var volumes = await _unitOfWork.VolumeRepository.GetVolumes(markReadDto.SeriesId);
|
||||
user.Progresses ??= new List<AppUserProgress>();
|
||||
foreach (var volume in volumes)
|
||||
{
|
||||
|
@ -125,7 +125,7 @@ namespace API.Controllers
|
|||
public async Task<ActionResult> MarkUnread(MarkReadDto markReadDto)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername(), AppUserIncludes.Progress);
|
||||
var volumes = await _unitOfWork.SeriesRepository.GetVolumes(markReadDto.SeriesId);
|
||||
var volumes = await _unitOfWork.VolumeRepository.GetVolumes(markReadDto.SeriesId);
|
||||
user.Progresses ??= new List<AppUserProgress>();
|
||||
foreach (var volume in volumes)
|
||||
{
|
||||
|
@ -267,7 +267,7 @@ namespace API.Controllers
|
|||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername(), AppUserIncludes.Progress);
|
||||
user.Progresses ??= new List<AppUserProgress>();
|
||||
|
||||
var volumes = await _unitOfWork.SeriesRepository.GetVolumesForSeriesAsync(dto.SeriesIds.ToArray(), true);
|
||||
var volumes = await _unitOfWork.VolumeRepository.GetVolumesForSeriesAsync(dto.SeriesIds.ToArray(), true);
|
||||
foreach (var volume in volumes)
|
||||
{
|
||||
_readerService.MarkChaptersAsRead(user, volume.SeriesId, volume.Chapters);
|
||||
|
@ -294,7 +294,7 @@ namespace API.Controllers
|
|||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername(), AppUserIncludes.Progress);
|
||||
user.Progresses ??= new List<AppUserProgress>();
|
||||
|
||||
var volumes = await _unitOfWork.SeriesRepository.GetVolumesForSeriesAsync(dto.SeriesIds.ToArray(), true);
|
||||
var volumes = await _unitOfWork.VolumeRepository.GetVolumesForSeriesAsync(dto.SeriesIds.ToArray(), true);
|
||||
foreach (var volume in volumes)
|
||||
{
|
||||
_readerService.MarkChaptersAsUnread(user, volume.SeriesId, volume.Chapters);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Comparators;
|
||||
|
@ -99,16 +100,20 @@ namespace API.Controllers
|
|||
[HttpPost("delete-item")]
|
||||
public async Task<ActionResult> DeleteListItem(UpdateReadingListPosition dto)
|
||||
{
|
||||
var items = (await _unitOfWork.ReadingListRepository.GetReadingListItemsByIdAsync(dto.ReadingListId)).ToList();
|
||||
var item = items.Find(r => r.Id == dto.ReadingListItemId);
|
||||
items.Remove(item);
|
||||
var readingList = await _unitOfWork.ReadingListRepository.GetReadingListByIdAsync(dto.ReadingListId);
|
||||
readingList.Items = readingList.Items.Where(r => r.Id != dto.ReadingListItemId).ToList();
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
|
||||
var index = 0;
|
||||
foreach (var readingListItem in readingList.Items)
|
||||
{
|
||||
items[i].Order = i;
|
||||
readingListItem.Order = index;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (_unitOfWork.HasChanges() && await _unitOfWork.CommitAsync())
|
||||
if (!_unitOfWork.HasChanges()) return Ok();
|
||||
|
||||
if (await _unitOfWork.CommitAsync())
|
||||
{
|
||||
return Ok("Updated");
|
||||
}
|
||||
|
@ -138,15 +143,10 @@ namespace API.Controllers
|
|||
itemIdsToRemove.Contains(r.Id));
|
||||
_unitOfWork.ReadingListRepository.BulkRemove(listItems);
|
||||
|
||||
if (_unitOfWork.HasChanges())
|
||||
{
|
||||
await _unitOfWork.CommitAsync();
|
||||
return Ok("Updated");
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ok("Nothing to remove");
|
||||
}
|
||||
if (!_unitOfWork.HasChanges()) return Ok("Nothing to remove");
|
||||
|
||||
await _unitOfWork.CommitAsync();
|
||||
return Ok("Updated");
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -437,7 +437,7 @@ namespace API.Controllers
|
|||
|
||||
var existingChapterExists = readingList.Items.Select(rli => rli.ChapterId).ToHashSet();
|
||||
var chaptersForSeries = (await _unitOfWork.ChapterRepository.GetChaptersByIdsAsync(chapterIds))
|
||||
.OrderBy(c => int.Parse(c.Volume.Name))
|
||||
.OrderBy(c => float.Parse(c.Volume.Name))
|
||||
.ThenBy(x => double.Parse(x.Number), _chapterSortComparerForInChapterSorting);
|
||||
|
||||
var index = lastOrder + 1;
|
||||
|
|
|
@ -10,9 +10,11 @@ using API.Entities;
|
|||
using API.Extensions;
|
||||
using API.Helpers;
|
||||
using API.Interfaces;
|
||||
using API.SignalR;
|
||||
using Kavita.Common;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace API.Controllers
|
||||
|
@ -22,12 +24,14 @@ namespace API.Controllers
|
|||
private readonly ILogger<SeriesController> _logger;
|
||||
private readonly ITaskScheduler _taskScheduler;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IHubContext<MessageHub> _messageHub;
|
||||
|
||||
public SeriesController(ILogger<SeriesController> logger, ITaskScheduler taskScheduler, IUnitOfWork unitOfWork)
|
||||
public SeriesController(ILogger<SeriesController> logger, ITaskScheduler taskScheduler, IUnitOfWork unitOfWork, IHubContext<MessageHub> messageHub)
|
||||
{
|
||||
_logger = logger;
|
||||
_taskScheduler = taskScheduler;
|
||||
_unitOfWork = unitOfWork;
|
||||
_messageHub = messageHub;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
|
@ -97,14 +101,14 @@ namespace API.Controllers
|
|||
public async Task<ActionResult<IEnumerable<VolumeDto>>> GetVolumes(int seriesId)
|
||||
{
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername());
|
||||
return Ok(await _unitOfWork.SeriesRepository.GetVolumesDtoAsync(seriesId, userId));
|
||||
return Ok(await _unitOfWork.VolumeRepository.GetVolumesDtoAsync(seriesId, userId));
|
||||
}
|
||||
|
||||
[HttpGet("volume")]
|
||||
public async Task<ActionResult<VolumeDto>> GetVolume(int volumeId)
|
||||
{
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername());
|
||||
return Ok(await _unitOfWork.SeriesRepository.GetVolumeDtoAsync(volumeId, userId));
|
||||
return Ok(await _unitOfWork.VolumeRepository.GetVolumeDtoAsync(volumeId, userId));
|
||||
}
|
||||
|
||||
[HttpGet("chapter")]
|
||||
|
@ -217,7 +221,7 @@ namespace API.Controllers
|
|||
[HttpPost("refresh-metadata")]
|
||||
public ActionResult RefreshSeriesMetadata(RefreshSeriesDto refreshSeriesDto)
|
||||
{
|
||||
_taskScheduler.RefreshSeriesMetadata(refreshSeriesDto.LibraryId, refreshSeriesDto.SeriesId);
|
||||
_taskScheduler.RefreshSeriesMetadata(refreshSeriesDto.LibraryId, refreshSeriesDto.SeriesId, true);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
@ -296,6 +300,12 @@ namespace API.Controllers
|
|||
|
||||
if (await _unitOfWork.CommitAsync())
|
||||
{
|
||||
foreach (var tag in updateSeriesMetadataDto.Tags)
|
||||
{
|
||||
await _messageHub.Clients.All.SendAsync(SignalREvents.SeriesAddedToCollection,
|
||||
MessageFactory.SeriesAddedToCollection(tag.Id,
|
||||
updateSeriesMetadataDto.SeriesMetadata.SeriesId));
|
||||
}
|
||||
return Ok("Successfully updated");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.DTOs.Settings;
|
||||
using API.Entities.Enums;
|
||||
using API.Extensions;
|
||||
using API.Helpers.Converters;
|
||||
using API.Interfaces;
|
||||
using API.Interfaces.Services;
|
||||
using API.Services;
|
||||
using Kavita.Common;
|
||||
using Kavita.Common.Extensions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
@ -21,12 +23,22 @@ namespace API.Controllers
|
|||
private readonly ILogger<SettingsController> _logger;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly ITaskScheduler _taskScheduler;
|
||||
private readonly IAccountService _accountService;
|
||||
|
||||
public SettingsController(ILogger<SettingsController> logger, IUnitOfWork unitOfWork, ITaskScheduler taskScheduler)
|
||||
public SettingsController(ILogger<SettingsController> logger, IUnitOfWork unitOfWork, ITaskScheduler taskScheduler, IAccountService accountService)
|
||||
{
|
||||
_logger = logger;
|
||||
_unitOfWork = unitOfWork;
|
||||
_taskScheduler = taskScheduler;
|
||||
_accountService = accountService;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet("base-url")]
|
||||
public async Task<ActionResult<string>> GetBaseUrl()
|
||||
{
|
||||
var settingsDto = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
|
||||
return Ok(settingsDto.BaseUrl);
|
||||
}
|
||||
|
||||
[Authorize(Policy = "RequireAdminRole")]
|
||||
|
@ -57,6 +69,7 @@ namespace API.Controllers
|
|||
|
||||
// We do not allow CacheDirectory changes, so we will ignore.
|
||||
var currentSettings = await _unitOfWork.SettingsRepository.GetSettingsAsync();
|
||||
var updateAuthentication = false;
|
||||
|
||||
foreach (var setting in currentSettings)
|
||||
{
|
||||
|
@ -80,6 +93,18 @@ namespace API.Controllers
|
|||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.BaseUrl && updateSettingsDto.BaseUrl + string.Empty != setting.Value)
|
||||
{
|
||||
var path = !updateSettingsDto.BaseUrl.StartsWith("/")
|
||||
? $"/{updateSettingsDto.BaseUrl}"
|
||||
: updateSettingsDto.BaseUrl;
|
||||
path = !path.EndsWith("/")
|
||||
? $"{path}/"
|
||||
: path;
|
||||
setting.Value = path;
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.LoggingLevel && updateSettingsDto.LoggingLevel + string.Empty != setting.Value)
|
||||
{
|
||||
setting.Value = updateSettingsDto.LoggingLevel + string.Empty;
|
||||
|
@ -93,6 +118,13 @@ namespace API.Controllers
|
|||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.EnableAuthentication && updateSettingsDto.EnableAuthentication + string.Empty != setting.Value)
|
||||
{
|
||||
setting.Value = updateSettingsDto.EnableAuthentication + string.Empty;
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
updateAuthentication = true;
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.AllowStatCollection && updateSettingsDto.AllowStatCollection + string.Empty != setting.Value)
|
||||
{
|
||||
setting.Value = updateSettingsDto.AllowStatCollection + string.Empty;
|
||||
|
@ -110,12 +142,33 @@ namespace API.Controllers
|
|||
|
||||
if (!_unitOfWork.HasChanges()) return Ok("Nothing was updated");
|
||||
|
||||
if (!_unitOfWork.HasChanges() || !await _unitOfWork.CommitAsync())
|
||||
try
|
||||
{
|
||||
await _unitOfWork.CommitAsync();
|
||||
|
||||
if (updateAuthentication)
|
||||
{
|
||||
var users = await _unitOfWork.UserRepository.GetNonAdminUsersAsync();
|
||||
foreach (var user in users)
|
||||
{
|
||||
var errors = await _accountService.ChangeUserPassword(user, AccountService.DefaultPassword);
|
||||
if (!errors.Any()) continue;
|
||||
|
||||
await _unitOfWork.RollbackAsync();
|
||||
return BadRequest(errors);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Server authentication changed. Updated all non-admins to default password");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "There was an exception when updating server settings");
|
||||
await _unitOfWork.RollbackAsync();
|
||||
return BadRequest("There was a critical issue. Please try again.");
|
||||
}
|
||||
|
||||
|
||||
_logger.LogInformation("Server Settings updated");
|
||||
_taskScheduler.ScheduleTasks();
|
||||
return Ok(updateSettingsDto);
|
||||
|
@ -148,5 +201,12 @@ namespace API.Controllers
|
|||
var settingsDto = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
|
||||
return Ok(settingsDto.EnableOpds);
|
||||
}
|
||||
|
||||
[HttpGet("authentication-enabled")]
|
||||
public async Task<ActionResult<bool>> GetAuthenticationEnabled()
|
||||
{
|
||||
var settingsDto = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
|
||||
return Ok(settingsDto.EnableAuthentication);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace API.Controllers
|
|||
chapter.CoverImage = filePath;
|
||||
chapter.CoverImageLocked = true;
|
||||
_unitOfWork.ChapterRepository.Update(chapter);
|
||||
var volume = await _unitOfWork.SeriesRepository.GetVolumeAsync(chapter.VolumeId);
|
||||
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(chapter.VolumeId);
|
||||
volume.CoverImage = chapter.CoverImage;
|
||||
_unitOfWork.VolumeRepository.Update(volume);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ namespace API.Controllers
|
|||
chapter.CoverImage = string.Empty;
|
||||
chapter.CoverImageLocked = false;
|
||||
_unitOfWork.ChapterRepository.Update(chapter);
|
||||
var volume = await _unitOfWork.SeriesRepository.GetVolumeAsync(chapter.VolumeId);
|
||||
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(chapter.VolumeId);
|
||||
volume.CoverImage = chapter.CoverImage;
|
||||
_unitOfWork.VolumeRepository.Update(volume);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(volume.SeriesId);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data.Repositories;
|
||||
using API.DTOs;
|
||||
using API.Extensions;
|
||||
using API.Interfaces;
|
||||
|
@ -38,11 +39,24 @@ namespace API.Controllers
|
|||
return Ok(await _unitOfWork.UserRepository.GetMembersAsync());
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet("names")]
|
||||
public async Task<ActionResult<IEnumerable<MemberDto>>> GetUserNames()
|
||||
{
|
||||
var setting = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
|
||||
if (setting.EnableAuthentication)
|
||||
{
|
||||
return Unauthorized("This API cannot be used given your server's configuration");
|
||||
}
|
||||
var members = await _unitOfWork.UserRepository.GetMembersAsync();
|
||||
return Ok(members.Select(m => m.Username));
|
||||
}
|
||||
|
||||
[HttpGet("has-reading-progress")]
|
||||
public async Task<ActionResult<bool>> HasReadingProgress(int libraryId)
|
||||
{
|
||||
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryId);
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername());
|
||||
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryId, LibraryIncludes.None);
|
||||
return Ok(await _unitOfWork.AppUserProgressRepository.UserHasProgress(library.Type, userId));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue