Release Testing Day 2 (#1493)
* Added a no data section to collection detail. * Remove an optimization for skipping the whole library scan as it wasn't reliable * When resetting password, ensure the input is colored correctly * Fixed setting new password after resetting, throwing an error despite it actually being successful. Fixed incorrect messaging for Password Reset page. * Fixed a bug where reset password would show the side nav button and skew the page. Updated a lot of references to use Typed version for formcontrols. * Removed a migration from 0.5.0, 6 releases ago. * Added a null check so we don't throw an exception when connecting with signalR on unauthenticated users.
This commit is contained in:
parent
8e21a7091f
commit
2cd94e7db4
32 changed files with 155 additions and 254 deletions
|
@ -579,17 +579,26 @@ namespace API.Controllers
|
|||
[HttpPost("confirm-password-reset")]
|
||||
public async Task<ActionResult<string>> ConfirmForgotPassword(ConfirmPasswordResetDto dto)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
if (user == null)
|
||||
try
|
||||
{
|
||||
return BadRequest("Invalid Details");
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
if (user == null)
|
||||
{
|
||||
return BadRequest("Invalid Details");
|
||||
}
|
||||
|
||||
var result = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider,
|
||||
"ResetPassword", dto.Token);
|
||||
if (!result) return BadRequest("Unable to reset password, your email token is not correct.");
|
||||
|
||||
var errors = await _accountService.ChangeUserPassword(user, dto.Password);
|
||||
return errors.Any() ? BadRequest(errors) : Ok("Password updated");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "There was an unexpected error when confirming new password");
|
||||
return BadRequest("There was an unexpected error when confirming new password");
|
||||
}
|
||||
|
||||
var result = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, "ResetPassword", dto.Token);
|
||||
if (!result) return BadRequest("Unable to reset password, your email token is not correct.");
|
||||
|
||||
var errors = await _accountService.ChangeUserPassword(user, dto.Password);
|
||||
return errors.Any() ? BadRequest(errors) : Ok("Password updated");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Comparators;
|
||||
using API.Entities.Enums;
|
||||
using API.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace API.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Responsible to migrate existing bookmarks to files. Introduced in v0.4.9.27
|
||||
/// </summary>
|
||||
public static class MigrateBookmarks
|
||||
{
|
||||
/// <summary>
|
||||
/// This will migrate existing bookmarks to bookmark folder based.
|
||||
/// If the bookmarks folder already exists, this will not run.
|
||||
/// </summary>
|
||||
/// <remarks>Bookmark directory is configurable. This will always use the default bookmark directory.</remarks>
|
||||
/// <param name="directoryService"></param>
|
||||
/// <param name="unitOfWork"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="cacheService"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task Migrate(IDirectoryService directoryService, IUnitOfWork unitOfWork,
|
||||
ILogger<Program> logger, ICacheService cacheService)
|
||||
{
|
||||
var bookmarkDirectory = (await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BookmarkDirectory))
|
||||
.Value;
|
||||
if (string.IsNullOrEmpty(bookmarkDirectory))
|
||||
{
|
||||
bookmarkDirectory = directoryService.BookmarkDirectory;
|
||||
}
|
||||
|
||||
if (directoryService.Exists(bookmarkDirectory)) return;
|
||||
|
||||
logger.LogInformation("Bookmark migration is needed....This may take some time");
|
||||
|
||||
var allBookmarks = (await unitOfWork.UserRepository.GetAllBookmarksAsync()).ToList();
|
||||
|
||||
var uniqueChapterIds = allBookmarks.Select(b => b.ChapterId).Distinct().ToList();
|
||||
var uniqueUserIds = allBookmarks.Select(b => b.AppUserId).Distinct().ToList();
|
||||
foreach (var userId in uniqueUserIds)
|
||||
{
|
||||
foreach (var chapterId in uniqueChapterIds)
|
||||
{
|
||||
var chapterBookmarks = allBookmarks.Where(b => b.ChapterId == chapterId).ToList();
|
||||
var chapterPages = chapterBookmarks
|
||||
.Select(b => b.Page).ToList();
|
||||
var seriesId = chapterBookmarks
|
||||
.Select(b => b.SeriesId).First();
|
||||
var mangaFiles = await unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapterId);
|
||||
var chapterExtractPath = directoryService.FileSystem.Path.Join(directoryService.TempDirectory, $"bookmark_c{chapterId}_u{userId}_s{seriesId}");
|
||||
|
||||
var numericComparer = new NumericComparer();
|
||||
if (!mangaFiles.Any()) continue;
|
||||
|
||||
switch (mangaFiles.First().Format)
|
||||
{
|
||||
case MangaFormat.Image:
|
||||
directoryService.ExistOrCreate(chapterExtractPath);
|
||||
directoryService.CopyFilesToDirectory(mangaFiles.Select(f => f.FilePath), chapterExtractPath);
|
||||
break;
|
||||
case MangaFormat.Archive:
|
||||
case MangaFormat.Pdf:
|
||||
cacheService.ExtractChapterFiles(chapterExtractPath, mangaFiles.ToList());
|
||||
break;
|
||||
case MangaFormat.Epub:
|
||||
continue;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
var files = directoryService.GetFilesWithExtension(chapterExtractPath, Services.Tasks.Scanner.Parser.Parser.ImageFileExtensions);
|
||||
// Filter out images that aren't in bookmarks
|
||||
Array.Sort(files, numericComparer);
|
||||
foreach (var chapterPage in chapterPages)
|
||||
{
|
||||
var file = files.ElementAt(chapterPage);
|
||||
var bookmark = allBookmarks.FirstOrDefault(b =>
|
||||
b.ChapterId == chapterId && b.SeriesId == seriesId && b.AppUserId == userId &&
|
||||
b.Page == chapterPage);
|
||||
if (bookmark == null) continue;
|
||||
|
||||
var filename = directoryService.FileSystem.Path.GetFileName(file);
|
||||
var newLocation = directoryService.FileSystem.Path.Join(
|
||||
ReaderService.FormatBookmarkFolderPath(String.Empty, userId, seriesId, chapterId),
|
||||
filename);
|
||||
bookmark.FileName = newLocation;
|
||||
directoryService.CopyFileToDirectory(file,
|
||||
ReaderService.FormatBookmarkFolderPath(bookmarkDirectory, userId, seriesId, chapterId));
|
||||
unitOfWork.UserRepository.Update(bookmark);
|
||||
}
|
||||
}
|
||||
// Clear temp after each user to avoid too much space being eaten
|
||||
directoryService.ClearDirectory(directoryService.TempDirectory);
|
||||
}
|
||||
|
||||
await unitOfWork.CommitAsync();
|
||||
// Run CleanupService as we cache a ton of files
|
||||
directoryService.ClearDirectory(directoryService.TempDirectory);
|
||||
|
||||
}
|
||||
}
|
|
@ -406,30 +406,6 @@ public class ScannerService : IScannerService
|
|||
var libraryFolderPaths = library.Folders.Select(fp => fp.Path).ToList();
|
||||
if (!await CheckMounts(library.Name, libraryFolderPaths)) return;
|
||||
|
||||
// If all library Folder paths haven't been modified since last scan, abort
|
||||
// Unless the user did something on the library (delete series) and thus we can bypass this check
|
||||
var wasLibraryUpdatedSinceLastScan = (library.LastModified.Truncate(TimeSpan.TicksPerMinute) >
|
||||
library.LastScanned.Truncate(TimeSpan.TicksPerMinute))
|
||||
&& library.LastScanned != DateTime.MinValue;
|
||||
if (!forceUpdate && !wasLibraryUpdatedSinceLastScan)
|
||||
{
|
||||
var haveFoldersChangedSinceLastScan = library.Folders
|
||||
.All(f => _directoryService.GetLastWriteTime(f.Path).Truncate(TimeSpan.TicksPerMinute) > f.LastScanned.Truncate(TimeSpan.TicksPerMinute));
|
||||
|
||||
// If nothing changed && library folder's have all been scanned at least once
|
||||
if (!haveFoldersChangedSinceLastScan && library.Folders.All(f => f.LastScanned > DateTime.MinValue))
|
||||
{
|
||||
_logger.LogInformation("[ScannerService] {LibraryName} scan has no work to do. All folders have not been changed since last scan", library.Name);
|
||||
await _eventHub.SendMessageAsync(MessageFactory.Info,
|
||||
MessageFactory.InfoEvent($"{library.Name} scan has no work to do",
|
||||
$"All folders have not been changed since last scan ({library.Folders.Max(f => f.LastScanned).ToString(CultureInfo.CurrentCulture)}). Scan will be aborted."));
|
||||
|
||||
BackgroundJob.Enqueue(() => _metadataService.GenerateCoversForLibrary(library.Id, false));
|
||||
BackgroundJob.Enqueue(() => _wordCountAnalyzerService.ScanLibrary(library.Id, false));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Validations are done, now we can start actual scan
|
||||
_logger.LogInformation("[ScannerService] Beginning file scan on {LibraryName}", library.Name);
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace API.SignalR.Presence
|
|||
public async Task UserConnected(string username, string connectionId)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username);
|
||||
if (user == null) return;
|
||||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
|
||||
lock (OnlineUsers)
|
||||
{
|
||||
|
|
|
@ -185,8 +185,6 @@ namespace API
|
|||
var themeService = serviceProvider.GetRequiredService<IThemeService>();
|
||||
var dataContext = serviceProvider.GetRequiredService<DataContext>();
|
||||
|
||||
await MigrateBookmarks.Migrate(directoryService, unitOfWork,
|
||||
logger, cacheService);
|
||||
|
||||
// Only run this if we are upgrading
|
||||
await MigrateChangePasswordRoles.Migrate(unitOfWork, userManager);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue