PR Flush (#3446)
Co-authored-by: Hippari <iamtimscampi@gmail.com> Co-authored-by: Gavin Mogan <github@gavinmogan.com>
This commit is contained in:
parent
0407d75d91
commit
bfbcb4b741
46 changed files with 551 additions and 364 deletions
|
@ -509,6 +509,21 @@ public class AccountController : BaseApiController
|
|||
_unitOfWork.UserRepository.Update(user);
|
||||
}
|
||||
|
||||
// Check if email is changing for a non-admin user
|
||||
var isUpdatingAnotherAccount = user.Id != adminUser.Id;
|
||||
if (isUpdatingAnotherAccount && !string.IsNullOrEmpty(dto.Email) && user.Email != dto.Email)
|
||||
{
|
||||
// Validate username change
|
||||
var errors = await _accountService.ValidateEmail(dto.Email);
|
||||
if (errors.Any()) return BadRequest(await _localizationService.Translate(User.GetUserId(), "email-taken"));
|
||||
|
||||
user.Email = dto.Email;
|
||||
user.EmailConfirmed = true; // When an admin performs the flow, we assume the email address is able to receive data
|
||||
|
||||
await _userManager.UpdateNormalizedEmailAsync(user);
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
}
|
||||
|
||||
// Update roles
|
||||
var existingRoles = await _userManager.GetRolesAsync(user);
|
||||
var hasAdminRole = dto.Roles.Contains(PolicyConstants.AdminRole);
|
||||
|
@ -612,8 +627,7 @@ public class AccountController : BaseApiController
|
|||
if (adminUser == null) return Unauthorized(await _localizationService.Translate(userId, "permission-denied"));
|
||||
|
||||
dto.Email = dto.Email.Trim();
|
||||
if (string.IsNullOrEmpty(dto.Email))
|
||||
return BadRequest(await _localizationService.Translate(userId, "invalid-payload"));
|
||||
if (string.IsNullOrEmpty(dto.Email)) return BadRequest(await _localizationService.Translate(userId, "invalid-payload"));
|
||||
|
||||
_logger.LogInformation("{User} is inviting {Email} to the server", adminUser.UserName, dto.Email);
|
||||
|
||||
|
@ -623,7 +637,7 @@ public class AccountController : BaseApiController
|
|||
{
|
||||
var invitedUser = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
if (await _userManager.IsEmailConfirmedAsync(invitedUser!))
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "user-already-registered", invitedUser.UserName));
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "user-already-registered", invitedUser!.UserName));
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "user-already-invited"));
|
||||
}
|
||||
|
||||
|
|
|
@ -18,4 +18,8 @@ public record UpdateUserDto
|
|||
/// An Age Rating which will limit the account to seeing everything equal to or below said rating.
|
||||
/// </summary>
|
||||
public AgeRestrictionDto AgeRestriction { get; init; } = default!;
|
||||
/// <summary>
|
||||
/// Email of the user
|
||||
/// </summary>
|
||||
public string? Email { get; set; } = default!;
|
||||
}
|
||||
|
|
|
@ -101,12 +101,15 @@ public static class RestrictByAgeExtensions
|
|||
|
||||
if (restriction.IncludeUnknowns)
|
||||
{
|
||||
return queryable.Where(c => c.SeriesMetadataPeople.All(sm =>
|
||||
sm.SeriesMetadata.AgeRating <= restriction.AgeRating));
|
||||
return queryable.Where(c =>
|
||||
c.SeriesMetadataPeople.Any(sm => sm.SeriesMetadata.AgeRating <= restriction.AgeRating) ||
|
||||
c.ChapterPeople.Any(cp => cp.Chapter.AgeRating <= restriction.AgeRating));
|
||||
}
|
||||
|
||||
return queryable.Where(c => c.SeriesMetadataPeople.All(sm =>
|
||||
sm.SeriesMetadata.AgeRating <= restriction.AgeRating && sm.SeriesMetadata.AgeRating > AgeRating.Unknown));
|
||||
return queryable.Where(c =>
|
||||
c.SeriesMetadataPeople.Any(sm => sm.SeriesMetadata.AgeRating <= restriction.AgeRating && sm.SeriesMetadata.AgeRating != AgeRating.Unknown) ||
|
||||
c.ChapterPeople.Any(cp => cp.Chapter.AgeRating <= restriction.AgeRating && cp.Chapter.AgeRating != AgeRating.Unknown)
|
||||
);
|
||||
}
|
||||
|
||||
public static IQueryable<ReadingList> RestrictAgainstAgeRestriction(this IQueryable<ReadingList> queryable, AgeRestriction restriction)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"age-restriction-update": "There was an error updating the age restriction",
|
||||
"no-user": "User does not exist",
|
||||
"username-taken": "Username already taken",
|
||||
"email-taken": "Email already in use",
|
||||
"user-already-confirmed": "User is already confirmed",
|
||||
"generic-user-update": "There was an exception when updating the user",
|
||||
"manual-setup-fail": "Manual setup is unable to be completed. Please cancel and recreate the invite",
|
||||
|
|
|
@ -95,12 +95,12 @@ public class AccountService : IAccountService
|
|||
public async Task<IEnumerable<ApiException>> ValidateEmail(string email)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(email);
|
||||
if (user == null) return Array.Empty<ApiException>();
|
||||
if (user == null) return [];
|
||||
|
||||
return new List<ApiException>()
|
||||
{
|
||||
return
|
||||
[
|
||||
new ApiException(400, "Email is already registered")
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -14,6 +14,7 @@ using API.DTOs.Stats.V3;
|
|||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Services.Plus;
|
||||
using API.Services.Tasks.Scanner.Parser;
|
||||
using Flurl.Http;
|
||||
using Kavita.Common.EnvironmentInfo;
|
||||
using Kavita.Common.Helpers;
|
||||
|
@ -231,11 +232,12 @@ public class StatsService : IStatsService
|
|||
{
|
||||
// If first time flow, just return 0
|
||||
if (!await _context.Chapter.AnyAsync()) return 0;
|
||||
|
||||
return await _context.Series
|
||||
.AsNoTracking()
|
||||
.AsSplitQuery()
|
||||
.MaxAsync(s => s.Volumes!
|
||||
.Where(v => v.MinNumber == 0)
|
||||
.Where(v => v.MinNumber == Parser.LooseLeafVolumeNumber)
|
||||
.SelectMany(v => v.Chapters!)
|
||||
.Count());
|
||||
}
|
||||
|
@ -262,13 +264,13 @@ public class StatsService : IStatsService
|
|||
dto.MaxSeriesInALibrary = await MaxSeriesInAnyLibrary();
|
||||
dto.MaxVolumesInASeries = await MaxVolumesInASeries();
|
||||
dto.MaxChaptersInASeries = await MaxChaptersInASeries();
|
||||
dto.TotalFiles = await _unitOfWork.LibraryRepository.GetTotalFiles();
|
||||
dto.TotalGenres = await _unitOfWork.GenreRepository.GetCountAsync();
|
||||
dto.TotalPeople = await _unitOfWork.PersonRepository.GetCountAsync();
|
||||
dto.TotalSeries = await _unitOfWork.SeriesRepository.GetCountAsync();
|
||||
dto.TotalLibraries = (await _unitOfWork.LibraryRepository.GetLibrariesAsync()).Count();
|
||||
dto.NumberOfCollections = (await _unitOfWork.CollectionTagRepository.GetAllCollectionsAsync()).Count();
|
||||
dto.NumberOfReadingLists = await _unitOfWork.ReadingListRepository.Count();
|
||||
dto.TotalFiles = await _context.MangaFile.CountAsync();
|
||||
dto.TotalGenres = await _context.Genre.CountAsync();
|
||||
dto.TotalPeople = await _context.Person.CountAsync();
|
||||
dto.TotalSeries = await _context.Series.CountAsync();
|
||||
dto.TotalLibraries = await _context.Library.CountAsync();
|
||||
dto.NumberOfCollections = await _context.AppUserCollection.CountAsync();
|
||||
dto.NumberOfReadingLists = await _context.ReadingList.CountAsync();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -314,6 +316,7 @@ public class StatsService : IStatsService
|
|||
libDto.UsingFolderWatching = library.FolderWatching;
|
||||
libDto.CreateCollectionsFromMetadata = library.ManageCollections;
|
||||
libDto.CreateReadingListsFromMetadata = library.ManageReadingLists;
|
||||
libDto.LibraryType = library.Type;
|
||||
|
||||
dto.Libraries.Add(libDto);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue