mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-06-01 20:54:12 -04:00
Transaction Support (#309)
* Added transactions to UnitOfWork and refactored code to use it. * This included blank UI fix from Kavita-webui
This commit is contained in:
parent
d2e444910d
commit
6e1b227e65
@ -82,6 +82,8 @@ namespace API.Controllers
|
|||||||
|
|
||||||
[HttpPost("register")]
|
[HttpPost("register")]
|
||||||
public async Task<ActionResult<UserDto>> Register(RegisterDto registerDto)
|
public async Task<ActionResult<UserDto>> Register(RegisterDto registerDto)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (await _userManager.Users.AnyAsync(x => x.NormalizedUserName == registerDto.Username.ToUpper()))
|
if (await _userManager.Users.AnyAsync(x => x.NormalizedUserName == registerDto.Username.ToUpper()))
|
||||||
{
|
{
|
||||||
@ -103,14 +105,17 @@ namespace API.Controllers
|
|||||||
// When we register an admin, we need to grant them access to all Libraries.
|
// When we register an admin, we need to grant them access to all Libraries.
|
||||||
if (registerDto.IsAdmin)
|
if (registerDto.IsAdmin)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("{UserName} is being registered as admin. Granting access to all libraries", user.UserName);
|
_logger.LogInformation("{UserName} is being registered as admin. Granting access to all libraries",
|
||||||
|
user.UserName);
|
||||||
var libraries = (await _unitOfWork.LibraryRepository.GetLibrariesAsync()).ToList();
|
var libraries = (await _unitOfWork.LibraryRepository.GetLibrariesAsync()).ToList();
|
||||||
foreach (var lib in libraries)
|
foreach (var lib in libraries)
|
||||||
{
|
{
|
||||||
lib.AppUsers ??= new List<AppUser>();
|
lib.AppUsers ??= new List<AppUser>();
|
||||||
lib.AppUsers.Add(user);
|
lib.AppUsers.Add(user);
|
||||||
}
|
}
|
||||||
if (libraries.Any() && !await _unitOfWork.Complete()) _logger.LogError("There was an issue granting library access. Please do this manually");
|
|
||||||
|
if (libraries.Any() && !await _unitOfWork.CommitAsync())
|
||||||
|
_logger.LogError("There was an issue granting library access. Please do this manually");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UserDto
|
return new UserDto
|
||||||
@ -120,6 +125,14 @@ namespace API.Controllers
|
|||||||
Preferences = _mapper.Map<UserPreferencesDto>(user.UserPreferences)
|
Preferences = _mapper.Map<UserPreferencesDto>(user.UserPreferences)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Something went wrong when registering user");
|
||||||
|
await _unitOfWork.RollbackAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return BadRequest("Something went wrong when registering user");
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("login")]
|
[HttpPost("login")]
|
||||||
public async Task<ActionResult<UserDto>> Login(LoginDto loginDto)
|
public async Task<ActionResult<UserDto>> Login(LoginDto loginDto)
|
||||||
@ -140,7 +153,7 @@ namespace API.Controllers
|
|||||||
user.UserPreferences ??= new AppUserPreferences();
|
user.UserPreferences ??= new AppUserPreferences();
|
||||||
|
|
||||||
_unitOfWork.UserRepository.Update(user);
|
_unitOfWork.UserRepository.Update(user);
|
||||||
await _unitOfWork.Complete();
|
await _unitOfWork.CommitAsync();
|
||||||
|
|
||||||
_logger.LogInformation("{UserName} logged in at {Time}", user.UserName, user.LastActive);
|
_logger.LogInformation("{UserName} logged in at {Time}", user.UserName, user.LastActive);
|
||||||
|
|
||||||
@ -167,7 +180,6 @@ namespace API.Controllers
|
|||||||
{
|
{
|
||||||
var user = await _userManager.Users
|
var user = await _userManager.Users
|
||||||
.Include(u => u.UserPreferences)
|
.Include(u => u.UserPreferences)
|
||||||
//.Include(u => u.UserRoles)
|
|
||||||
.SingleOrDefaultAsync(x => x.NormalizedUserName == updateRbsDto.Username.ToUpper());
|
.SingleOrDefaultAsync(x => x.NormalizedUserName == updateRbsDto.Username.ToUpper());
|
||||||
if (updateRbsDto.Roles.Contains(PolicyConstants.AdminRole) ||
|
if (updateRbsDto.Roles.Contains(PolicyConstants.AdminRole) ||
|
||||||
updateRbsDto.Roles.Contains(PolicyConstants.PlebRole))
|
updateRbsDto.Roles.Contains(PolicyConstants.PlebRole))
|
||||||
@ -183,11 +195,17 @@ namespace API.Controllers
|
|||||||
var rolesToRemove = existingRoles.Except(updateRbsDto.Roles);
|
var rolesToRemove = existingRoles.Except(updateRbsDto.Roles);
|
||||||
var result = await _userManager.AddToRolesAsync(user, updateRbsDto.Roles);
|
var result = await _userManager.AddToRolesAsync(user, updateRbsDto.Roles);
|
||||||
|
|
||||||
if (!result.Succeeded) return BadRequest("Something went wrong, unable to update user's roles");
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
await _unitOfWork.RollbackAsync();
|
||||||
|
return BadRequest("Something went wrong, unable to update user's roles");
|
||||||
|
}
|
||||||
if ((await _userManager.RemoveFromRolesAsync(user, rolesToRemove)).Succeeded)
|
if ((await _userManager.RemoveFromRolesAsync(user, rolesToRemove)).Succeeded)
|
||||||
{
|
{
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _unitOfWork.RollbackAsync();
|
||||||
return BadRequest("Something went wrong, unable to update user's roles");
|
return BadRequest("Something went wrong, unable to update user's roles");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using API.Constants;
|
using API.Constants;
|
||||||
@ -33,13 +34,9 @@ namespace API.Controllers
|
|||||||
{
|
{
|
||||||
return await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync();
|
return await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return await _unitOfWork.CollectionTagRepository.GetAllPromotedTagDtosAsync();
|
return await _unitOfWork.CollectionTagRepository.GetAllPromotedTagDtosAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(Policy = "RequireAdminRole")]
|
[Authorize(Policy = "RequireAdminRole")]
|
||||||
[HttpGet("search")]
|
[HttpGet("search")]
|
||||||
public async Task<IEnumerable<CollectionTagDto>> SearchTags(string queryString)
|
public async Task<IEnumerable<CollectionTagDto>> SearchTags(string queryString)
|
||||||
@ -64,7 +61,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
if (_unitOfWork.HasChanges())
|
if (_unitOfWork.HasChanges())
|
||||||
{
|
{
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok("Tag updated successfully");
|
return Ok("Tag updated successfully");
|
||||||
}
|
}
|
||||||
@ -80,6 +77,8 @@ namespace API.Controllers
|
|||||||
[Authorize(Policy = "RequireAdminRole")]
|
[Authorize(Policy = "RequireAdminRole")]
|
||||||
[HttpPost("update-series")]
|
[HttpPost("update-series")]
|
||||||
public async Task<ActionResult> UpdateSeriesForTag(UpdateSeriesForTagDto updateSeriesForTagDto)
|
public async Task<ActionResult> UpdateSeriesForTag(UpdateSeriesForTagDto updateSeriesForTagDto)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var tag = await _unitOfWork.CollectionTagRepository.GetFullTagAsync(updateSeriesForTagDto.Tag.Id);
|
var tag = await _unitOfWork.CollectionTagRepository.GetFullTagAsync(updateSeriesForTagDto.Tag.Id);
|
||||||
if (tag == null) return BadRequest("Not a valid Tag");
|
if (tag == null) return BadRequest("Not a valid Tag");
|
||||||
@ -103,16 +102,18 @@ namespace API.Controllers
|
|||||||
_unitOfWork.CollectionTagRepository.Remove(tag);
|
_unitOfWork.CollectionTagRepository.Remove(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_unitOfWork.HasChanges() && await _unitOfWork.Complete())
|
if (_unitOfWork.HasChanges() && await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok("Tag updated");
|
return Ok("Tag updated");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _unitOfWork.RollbackAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return BadRequest("Something went wrong. Please try again.");
|
return BadRequest("Something went wrong. Please try again.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -67,7 +67,7 @@ namespace API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!await _unitOfWork.Complete()) return BadRequest("There was a critical issue. Please try again.");
|
if (!await _unitOfWork.CommitAsync()) return BadRequest("There was a critical issue. Please try again.");
|
||||||
|
|
||||||
_logger.LogInformation("Created a new library: {LibraryName}", library.Name);
|
_logger.LogInformation("Created a new library: {LibraryName}", library.Name);
|
||||||
_taskScheduler.ScanLibrary(library.Id);
|
_taskScheduler.ScanLibrary(library.Id);
|
||||||
@ -133,7 +133,7 @@ namespace API.Controllers
|
|||||||
return Ok(_mapper.Map<MemberDto>(user));
|
return Ok(_mapper.Map<MemberDto>(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Added: {SelectedLibraries} to {Username}",libraryString, updateLibraryForUserDto.Username);
|
_logger.LogInformation("Added: {SelectedLibraries} to {Username}",libraryString, updateLibraryForUserDto.Username);
|
||||||
return Ok(_mapper.Map<MemberDto>(user));
|
return Ok(_mapper.Map<MemberDto>(user));
|
||||||
@ -199,7 +199,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
_unitOfWork.LibraryRepository.Update(library);
|
_unitOfWork.LibraryRepository.Update(library);
|
||||||
|
|
||||||
if (!await _unitOfWork.Complete()) return BadRequest("There was a critical issue updating the library.");
|
if (!await _unitOfWork.CommitAsync()) return BadRequest("There was a critical issue updating the library.");
|
||||||
if (differenceBetweenFolders.Any())
|
if (differenceBetweenFolders.Any())
|
||||||
{
|
{
|
||||||
_taskScheduler.ScanLibrary(library.Id, true);
|
_taskScheduler.ScanLibrary(library.Id, true);
|
||||||
|
@ -116,7 +116,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
_unitOfWork.UserRepository.Update(user);
|
_unitOfWork.UserRepository.Update(user);
|
||||||
|
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
_unitOfWork.UserRepository.Update(user);
|
_unitOfWork.UserRepository.Update(user);
|
||||||
|
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
_unitOfWork.UserRepository.Update(user);
|
_unitOfWork.UserRepository.Update(user);
|
||||||
|
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
_unitOfWork.UserRepository.Update(user);
|
_unitOfWork.UserRepository.Update(user);
|
||||||
|
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
_unitOfWork.UserRepository.Update(user);
|
_unitOfWork.UserRepository.Update(user);
|
||||||
|
|
||||||
if (!await _unitOfWork.Complete()) return BadRequest("There was a critical error.");
|
if (!await _unitOfWork.CommitAsync()) return BadRequest("There was a critical error.");
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -139,7 +139,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
_unitOfWork.SeriesRepository.Update(series);
|
_unitOfWork.SeriesRepository.Update(series);
|
||||||
|
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -189,6 +189,8 @@ namespace API.Controllers
|
|||||||
|
|
||||||
[HttpPost("metadata")]
|
[HttpPost("metadata")]
|
||||||
public async Task<ActionResult> UpdateSeriesMetadata(UpdateSeriesMetadataDto updateSeriesMetadataDto)
|
public async Task<ActionResult> UpdateSeriesMetadata(UpdateSeriesMetadataDto updateSeriesMetadataDto)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var seriesId = updateSeriesMetadataDto.SeriesMetadata.SeriesId;
|
var seriesId = updateSeriesMetadataDto.SeriesMetadata.SeriesId;
|
||||||
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(seriesId);
|
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(seriesId);
|
||||||
@ -242,10 +244,15 @@ namespace API.Controllers
|
|||||||
return Ok("No changes to save");
|
return Ok("No changes to save");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok("Successfully updated");
|
return Ok("Successfully updated");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _unitOfWork.RollbackAsync();
|
||||||
|
}
|
||||||
|
|
||||||
return BadRequest("Could not update metadata");
|
return BadRequest("Could not update metadata");
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ namespace API.Controllers
|
|||||||
_configuration.GetSection("Logging:LogLevel:Default").Value = updateSettingsDto.LoggingLevel + "";
|
_configuration.GetSection("Logging:LogLevel:Default").Value = updateSettingsDto.LoggingLevel + "";
|
||||||
if (!_unitOfWork.HasChanges()) return Ok("Nothing was updated");
|
if (!_unitOfWork.HasChanges()) return Ok("Nothing was updated");
|
||||||
|
|
||||||
if (!_unitOfWork.HasChanges() || !await _unitOfWork.Complete())
|
if (!_unitOfWork.HasChanges() || !await _unitOfWork.CommitAsync())
|
||||||
return BadRequest("There was a critical issue. Please try again.");
|
return BadRequest("There was a critical issue. Please try again.");
|
||||||
|
|
||||||
_logger.LogInformation("Server Settings updated");
|
_logger.LogInformation("Server Settings updated");
|
||||||
|
@ -26,7 +26,7 @@ namespace API.Controllers
|
|||||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username);
|
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username);
|
||||||
_unitOfWork.UserRepository.Delete(user);
|
_unitOfWork.UserRepository.Delete(user);
|
||||||
|
|
||||||
if (await _unitOfWork.Complete()) return Ok();
|
if (await _unitOfWork.CommitAsync()) return Ok();
|
||||||
|
|
||||||
return BadRequest("Could not delete the user.");
|
return BadRequest("Could not delete the user.");
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ namespace API.Controllers
|
|||||||
|
|
||||||
_unitOfWork.UserRepository.Update(existingPreferences);
|
_unitOfWork.UserRepository.Update(existingPreferences);
|
||||||
|
|
||||||
if (await _unitOfWork.Complete())
|
if (await _unitOfWork.CommitAsync())
|
||||||
{
|
{
|
||||||
return Ok(preferencesDto);
|
return Ok(preferencesDto);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,11 @@ namespace API.Data
|
|||||||
public IAppUserProgressRepository AppUserProgressRepository => new AppUserProgressRepository(_context);
|
public IAppUserProgressRepository AppUserProgressRepository => new AppUserProgressRepository(_context);
|
||||||
public ICollectionTagRepository CollectionTagRepository => new CollectionTagRepository(_context, _mapper);
|
public ICollectionTagRepository CollectionTagRepository => new CollectionTagRepository(_context, _mapper);
|
||||||
|
|
||||||
public async Task<bool> Complete()
|
public bool Commit()
|
||||||
|
{
|
||||||
|
return _context.SaveChanges() > 0;
|
||||||
|
}
|
||||||
|
public async Task<bool> CommitAsync()
|
||||||
{
|
{
|
||||||
return await _context.SaveChangesAsync() > 0;
|
return await _context.SaveChangesAsync() > 0;
|
||||||
}
|
}
|
||||||
@ -39,5 +43,16 @@ namespace API.Data
|
|||||||
{
|
{
|
||||||
return _context.ChangeTracker.HasChanges();
|
return _context.ChangeTracker.HasChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> RollbackAsync()
|
||||||
|
{
|
||||||
|
await _context.DisposeAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public bool Rollback()
|
||||||
|
{
|
||||||
|
_context.Dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,10 @@ namespace API.Interfaces
|
|||||||
ISettingsRepository SettingsRepository { get; }
|
ISettingsRepository SettingsRepository { get; }
|
||||||
IAppUserProgressRepository AppUserProgressRepository { get; }
|
IAppUserProgressRepository AppUserProgressRepository { get; }
|
||||||
ICollectionTagRepository CollectionTagRepository { get; }
|
ICollectionTagRepository CollectionTagRepository { get; }
|
||||||
Task<bool> Complete();
|
bool Commit();
|
||||||
|
Task<bool> CommitAsync();
|
||||||
bool HasChanges();
|
bool HasChanges();
|
||||||
|
bool Rollback();
|
||||||
|
Task<bool> RollbackAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -158,7 +158,7 @@ namespace API.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (_unitOfWork.HasChanges() && Task.Run(() => _unitOfWork.Complete()).Result)
|
if (_unitOfWork.HasChanges() && Task.Run(() => _unitOfWork.CommitAsync()).Result)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Updated metadata for {LibraryName} in {ElapsedMilliseconds} milliseconds", library.Name, sw.ElapsedMilliseconds);
|
_logger.LogInformation("Updated metadata for {LibraryName} in {ElapsedMilliseconds} milliseconds", library.Name, sw.ElapsedMilliseconds);
|
||||||
}
|
}
|
||||||
@ -191,7 +191,7 @@ namespace API.Services
|
|||||||
_unitOfWork.SeriesRepository.Update(series);
|
_unitOfWork.SeriesRepository.Update(series);
|
||||||
|
|
||||||
|
|
||||||
if (_unitOfWork.HasChanges() && Task.Run(() => _unitOfWork.Complete()).Result)
|
if (_unitOfWork.HasChanges() && Task.Run(() => _unitOfWork.CommitAsync()).Result)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Updated metadata for {SeriesName} in {ElapsedMilliseconds} milliseconds", series.Name, sw.ElapsedMilliseconds);
|
_logger.LogInformation("Updated metadata for {SeriesName} in {ElapsedMilliseconds} milliseconds", series.Name, sw.ElapsedMilliseconds);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ namespace API.Services.Tasks
|
|||||||
UpdateLibrary(library, series);
|
UpdateLibrary(library, series);
|
||||||
|
|
||||||
_unitOfWork.LibraryRepository.Update(library);
|
_unitOfWork.LibraryRepository.Update(library);
|
||||||
if (Task.Run(() => _unitOfWork.Complete()).Result)
|
if (Task.Run(() => _unitOfWork.CommitAsync()).Result)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Processed {TotalFiles} files and {ParsedSeriesCount} series in {ElapsedScanTime} milliseconds for {LibraryName}", totalFiles, series.Keys.Count, sw.ElapsedMilliseconds + scanElapsedTime, library.Name);
|
_logger.LogInformation("Processed {TotalFiles} files and {ParsedSeriesCount} series in {ElapsedScanTime} milliseconds for {LibraryName}", totalFiles, series.Keys.Count, sw.ElapsedMilliseconds + scanElapsedTime, library.Name);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user