mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-08-11 09:13:42 -04:00
589 lines
21 KiB
C#
589 lines
21 KiB
C#
using System.Collections.Generic;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Linq;
|
|
using System.Security.Claims;
|
|
using System.Threading.Tasks;
|
|
using API.Constants;
|
|
using API.Data;
|
|
using API.DTOs.Settings;
|
|
using API.Entities;
|
|
using API.Entities.Enums;
|
|
using API.Helpers.Builders;
|
|
using API.Services;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using NSubstitute;
|
|
using Xunit;
|
|
|
|
namespace API.Tests.Services;
|
|
|
|
public class OidcServiceTests: AbstractDbTest
|
|
{
|
|
|
|
[Fact]
|
|
public async Task UserSync_Username()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, _, _, userManager) = await Setup();
|
|
|
|
var user = new AppUserBuilder("holo", "holo@localhost")
|
|
.WithIdentityProvider(IdentityProvider.OpenIdConnect)
|
|
.Build();
|
|
var res = await userManager.CreateAsync(user);
|
|
Assert.Empty(res.Errors);
|
|
Assert.True(res.Succeeded);
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Name, "amelia"),
|
|
new (ClaimTypes.GivenName, "Lawrence"),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
// name is updated as the current username is not found, amelia is skipped as it is alredy in use
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
var dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal("Lawrence", user.UserName);
|
|
|
|
claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Name, "amelia"),
|
|
new (ClaimTypes.GivenName, "Lawrence"),
|
|
new (ClaimTypes.Surname, "Norah"),
|
|
};
|
|
identity = new ClaimsIdentity(claims);
|
|
principal = new ClaimsPrincipal(identity);
|
|
|
|
// Ensure a name longer down the list isn't picked if the current username is found
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal("Lawrence", user.UserName);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UserSync_CustomClaim()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var mangaLib = new LibraryBuilder("Manga", LibraryType.Manga).Build();
|
|
var lightNovelsLib = new LibraryBuilder("Light Novels", LibraryType.LightNovel).Build();
|
|
|
|
UnitOfWork.LibraryRepository.Add(mangaLib);
|
|
UnitOfWork.LibraryRepository.Add(lightNovelsLib);
|
|
await UnitOfWork.CommitAsync();
|
|
|
|
const string claim = "groups";
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (claim, PolicyConstants.LoginRole),
|
|
new (claim, PolicyConstants.DownloadRole),
|
|
new (ClaimTypes.Role, PolicyConstants.PromoteRole),
|
|
new (claim, OidcService.AgeRestrictionPrefix + "M"),
|
|
new (claim, OidcService.LibraryAccessPrefix + "Manga"),
|
|
new (ClaimTypes.Role, OidcService.LibraryAccessPrefix + "Light Novels"),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
RolesClaim = claim,
|
|
};
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
// Check correct roles assigned
|
|
var userRoles = await UnitOfWork.UserRepository.GetRoles(user.Id);
|
|
Assert.Contains(PolicyConstants.LoginRole, userRoles);
|
|
Assert.Contains(PolicyConstants.DownloadRole, userRoles);
|
|
Assert.DoesNotContain(PolicyConstants.PromoteRole, userRoles);
|
|
|
|
// Check correct libraries
|
|
var libraries = (await UnitOfWork.LibraryRepository.GetLibrariesForUserIdAsync(user.Id)).Select(l => l.Name).ToList();
|
|
Assert.Single(libraries);
|
|
Assert.Contains(mangaLib.Name, libraries);
|
|
Assert.DoesNotContain(lightNovelsLib.Name, libraries);
|
|
|
|
// Check correct age restrictions
|
|
var dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal(AgeRating.Mature, dbUser.AgeRestriction);
|
|
Assert.False(dbUser.AgeRestrictionIncludeUnknowns);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UserSync_CustomPrefix()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var mangaLib = new LibraryBuilder("Manga", LibraryType.Manga).Build();
|
|
var lightNovelsLib = new LibraryBuilder("Light Novels", LibraryType.LightNovel).Build();
|
|
|
|
UnitOfWork.LibraryRepository.Add(mangaLib);
|
|
UnitOfWork.LibraryRepository.Add(lightNovelsLib);
|
|
await UnitOfWork.CommitAsync();
|
|
|
|
const string prefix = "kavita-";
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Role, prefix + PolicyConstants.LoginRole),
|
|
new (ClaimTypes.Role, prefix + PolicyConstants.DownloadRole),
|
|
new (ClaimTypes.Role, PolicyConstants.PromoteRole),
|
|
new (ClaimTypes.Role, prefix + OidcService.AgeRestrictionPrefix + "M"),
|
|
new (ClaimTypes.Role, prefix + OidcService.LibraryAccessPrefix + "Manga"),
|
|
new (ClaimTypes.Role, OidcService.LibraryAccessPrefix + "Light Novels"),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
RolesPrefix = prefix,
|
|
};
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
// Check correct roles assigned
|
|
var userRoles = await UnitOfWork.UserRepository.GetRoles(user.Id);
|
|
Assert.Contains(PolicyConstants.LoginRole, userRoles);
|
|
Assert.Contains(PolicyConstants.DownloadRole, userRoles);
|
|
Assert.DoesNotContain(PolicyConstants.PromoteRole, userRoles);
|
|
|
|
// Check correct libraries
|
|
var libraries = (await UnitOfWork.LibraryRepository.GetLibrariesForUserIdAsync(user.Id)).Select(l => l.Name).ToList();
|
|
Assert.Single(libraries);
|
|
Assert.Contains(mangaLib.Name, libraries);
|
|
Assert.DoesNotContain(lightNovelsLib.Name, libraries);
|
|
|
|
// Check correct age restrictions
|
|
var dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal(AgeRating.Mature, dbUser.AgeRestriction);
|
|
Assert.False(dbUser.AgeRestrictionIncludeUnknowns);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SyncRoles()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Role, PolicyConstants.LoginRole),
|
|
new (ClaimTypes.Role, PolicyConstants.DownloadRole),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
var userRoles = await UnitOfWork.UserRepository.GetRoles(user.Id);
|
|
Assert.Contains(PolicyConstants.LoginRole, userRoles);
|
|
Assert.Contains(PolicyConstants.DownloadRole, userRoles);
|
|
|
|
// Only give one role
|
|
claims = [new Claim(ClaimTypes.Role, PolicyConstants.LoginRole)];
|
|
identity = new ClaimsIdentity(claims);
|
|
principal = new ClaimsPrincipal(identity);
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
userRoles = await UnitOfWork.UserRepository.GetRoles(user.Id);
|
|
Assert.Contains(PolicyConstants.LoginRole, userRoles);
|
|
Assert.DoesNotContain(PolicyConstants.DownloadRole, userRoles);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SyncLibraries()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var mangaLib = new LibraryBuilder("Manga", LibraryType.Manga).Build();
|
|
var lightNovelsLib = new LibraryBuilder("Light Novels", LibraryType.LightNovel).Build();
|
|
|
|
UnitOfWork.LibraryRepository.Add(mangaLib);
|
|
UnitOfWork.LibraryRepository.Add(lightNovelsLib);
|
|
await UnitOfWork.CommitAsync();
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Role, OidcService.LibraryAccessPrefix + "Manga"),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
var libraries = (await UnitOfWork.LibraryRepository.GetLibrariesForUserIdAsync(user.Id)).Select(l => l.Name).ToList();
|
|
Assert.Single(libraries);
|
|
Assert.Contains(mangaLib.Name, libraries);
|
|
Assert.DoesNotContain(lightNovelsLib.Name, libraries);
|
|
|
|
// Only give access to the other library
|
|
claims = [new Claim(ClaimTypes.Role, OidcService.LibraryAccessPrefix + "Light Novels")];
|
|
identity = new ClaimsIdentity(claims);
|
|
principal = new ClaimsPrincipal(identity);
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
// Check access has swicthed
|
|
libraries = (await UnitOfWork.LibraryRepository.GetLibrariesForUserIdAsync(user.Id)).Select(l => l.Name).ToList();
|
|
Assert.Single(libraries);
|
|
Assert.Contains(lightNovelsLib.Name, libraries);
|
|
Assert.DoesNotContain(mangaLib.Name, libraries);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SyncAgeRestrictions_NoRestrictions()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Role, OidcService.AgeRestrictionPrefix + "Not Applicable"),
|
|
new(ClaimTypes.Role, OidcService.AgeRestrictionPrefix + OidcService.IncludeUnknowns),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
var dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal(AgeRating.NotApplicable, dbUser.AgeRestriction);
|
|
Assert.True(dbUser.AgeRestrictionIncludeUnknowns);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SyncAgeRestrictions_IncludeUnknowns()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Role, OidcService.AgeRestrictionPrefix + "M"),
|
|
new(ClaimTypes.Role, OidcService.AgeRestrictionPrefix + OidcService.IncludeUnknowns),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
var dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal(AgeRating.Mature, dbUser.AgeRestriction);
|
|
Assert.True(dbUser.AgeRestrictionIncludeUnknowns);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SyncAgeRestriction_AdminNone()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Role, PolicyConstants.AdminRole),
|
|
new (ClaimTypes.Role, OidcService.AgeRestrictionPrefix + "M"),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
var dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal(AgeRating.NotApplicable, dbUser.AgeRestriction);
|
|
Assert.True(dbUser.AgeRestrictionIncludeUnknowns);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SyncAgeRestriction_MultipleAgeRestrictionClaims()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Role, OidcService.AgeRestrictionPrefix + "Teen"),
|
|
new (ClaimTypes.Role, OidcService.AgeRestrictionPrefix + "M"),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
var dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal(AgeRating.Mature, dbUser.AgeRestriction);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SyncAgeRestriction_NoAgeRestrictionClaims()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, user, _, _) = await Setup();
|
|
|
|
var identity = new ClaimsIdentity([]);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
var dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal(AgeRating.NotApplicable, dbUser.AgeRestriction);
|
|
Assert.True(dbUser.AgeRestrictionIncludeUnknowns);
|
|
|
|
// Also default to no restrictions when only include unknowns is present
|
|
identity = new ClaimsIdentity([new Claim(ClaimTypes.Role, OidcService.AgeRestrictionPrefix + OidcService.IncludeUnknowns)]);
|
|
principal = new ClaimsPrincipal(identity);
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
dbUser = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(dbUser);
|
|
Assert.Equal(AgeRating.NotApplicable, dbUser.AgeRestriction);
|
|
Assert.True(dbUser.AgeRestrictionIncludeUnknowns);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SyncUserSettings_DontChangeDefaultAdmin()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, _, _, userManager) = await Setup();
|
|
|
|
// Make user default user
|
|
var user = await UnitOfWork.UserRepository.GetDefaultAdminUser();
|
|
|
|
var settings = new OidcConfigDto
|
|
{
|
|
SyncUserSettings = true,
|
|
};
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new (ClaimTypes.Role, PolicyConstants.ChangePasswordRole),
|
|
new (ClaimTypes.Role, OidcService.AgeRestrictionPrefix + "Teen"),
|
|
};
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, user);
|
|
|
|
var userFromDb = await UnitOfWork.UserRepository.GetUserByIdAsync(user.Id);
|
|
Assert.NotNull(userFromDb);
|
|
Assert.NotEqual(AgeRating.Teen, userFromDb.AgeRestriction);
|
|
|
|
var newUser = new AppUserBuilder("NotAnAdmin", "NotAnAdmin@localhost")
|
|
.WithIdentityProvider(IdentityProvider.OpenIdConnect)
|
|
.Build();
|
|
var res = await userManager.CreateAsync(newUser);
|
|
Assert.Empty(res.Errors);
|
|
Assert.True(res.Succeeded);
|
|
|
|
await oidcService.SyncUserSettings(null!, settings, principal, newUser);
|
|
userFromDb = await UnitOfWork.UserRepository.GetUserByIdAsync(newUser.Id);
|
|
Assert.NotNull(userFromDb);
|
|
Assert.True(await userManager.IsInRoleAsync(newUser, PolicyConstants.ChangePasswordRole));
|
|
Assert.Equal(AgeRating.Teen, userFromDb.AgeRestriction);
|
|
|
|
}
|
|
|
|
[Fact]
|
|
public async Task FindBestAvailableName_NoDuplicates()
|
|
{
|
|
await ResetDb();
|
|
var (oidcService, _, _, userManager) = await Setup();
|
|
|
|
|
|
const string preferredName = "PreferredName";
|
|
const string name = "Name";
|
|
const string givenName = "GivenName";
|
|
const string surname = "Surname";
|
|
const string email = "Email";
|
|
|
|
var claims = new List<Claim>()
|
|
{
|
|
new(JwtRegisteredClaimNames.PreferredUsername, preferredName),
|
|
new(ClaimTypes.Name, name),
|
|
new(ClaimTypes.GivenName, givenName),
|
|
new(ClaimTypes.Surname, surname),
|
|
new(ClaimTypes.Email, email),
|
|
};
|
|
|
|
var identity = new ClaimsIdentity(claims);
|
|
var principal = new ClaimsPrincipal(identity);
|
|
|
|
var bestName = await oidcService.FindBestAvailableName(principal);
|
|
Assert.NotNull(bestName);
|
|
Assert.Equal(preferredName, bestName);
|
|
|
|
// Create user with this name to make the method fallback to the next claim
|
|
var user = new AppUserBuilder(bestName, bestName).Build();
|
|
var res = await userManager.CreateAsync(user);
|
|
// This has actual information as to why it would fail, so we check it to make sure if the test fail here we know why
|
|
Assert.Empty(res.Errors);
|
|
Assert.True(res.Succeeded);
|
|
|
|
// Fallback to name
|
|
bestName = await oidcService.FindBestAvailableName(principal);
|
|
Assert.NotNull(bestName);
|
|
Assert.Equal(name, bestName);
|
|
|
|
user = new AppUserBuilder(bestName, bestName).Build();
|
|
res = await userManager.CreateAsync(user);
|
|
Assert.Empty(res.Errors);
|
|
Assert.True(res.Succeeded);
|
|
|
|
// Fallback to given name
|
|
bestName = await oidcService.FindBestAvailableName(principal);
|
|
Assert.NotNull(bestName);
|
|
Assert.Equal(givenName, bestName);
|
|
|
|
user = new AppUserBuilder(bestName, bestName).Build();
|
|
res = await userManager.CreateAsync(user);
|
|
Assert.Empty(res.Errors);
|
|
Assert.True(res.Succeeded);
|
|
|
|
// Fallback to surname
|
|
bestName = await oidcService.FindBestAvailableName(principal);
|
|
Assert.NotNull(bestName);
|
|
Assert.Equal(surname, bestName);
|
|
|
|
user = new AppUserBuilder(bestName, bestName).Build();
|
|
res = await userManager.CreateAsync(user);
|
|
Assert.Empty(res.Errors);
|
|
Assert.True(res.Succeeded);
|
|
|
|
// When none are found, returns null
|
|
bestName = await oidcService.FindBestAvailableName(principal);
|
|
Assert.Null(bestName);
|
|
}
|
|
|
|
private async Task<(OidcService, AppUser, IAccountService, UserManager<AppUser>)> Setup()
|
|
{
|
|
var defaultAdmin = new AppUserBuilder("defaultAdmin", "defaultAdmin@localhost")
|
|
.WithRole(PolicyConstants.AdminRole)
|
|
.Build();
|
|
var user = new AppUserBuilder("amelia", "amelia@localhost")
|
|
.WithIdentityProvider(IdentityProvider.OpenIdConnect)
|
|
.Build();
|
|
|
|
var roleStore = new RoleStore<
|
|
AppRole,
|
|
DataContext,
|
|
int,
|
|
IdentityUserRole<int>,
|
|
IdentityRoleClaim<int>
|
|
>(Context);
|
|
|
|
var roleManager = new RoleManager<AppRole>(
|
|
roleStore,
|
|
[new RoleValidator<AppRole>()],
|
|
new UpperInvariantLookupNormalizer(),
|
|
new IdentityErrorDescriber(),
|
|
Substitute.For<ILogger<RoleManager<AppRole>>>());
|
|
|
|
foreach (var role in PolicyConstants.ValidRoles)
|
|
{
|
|
if (!await roleManager.RoleExistsAsync(role))
|
|
{
|
|
await roleManager.CreateAsync(new AppRole
|
|
{
|
|
Name = role,
|
|
});
|
|
}
|
|
}
|
|
|
|
var userStore = new UserStore<
|
|
AppUser,
|
|
AppRole,
|
|
DataContext,
|
|
int,
|
|
IdentityUserClaim<int>,
|
|
AppUserRole,
|
|
IdentityUserLogin<int>,
|
|
IdentityUserToken<int>,
|
|
IdentityRoleClaim<int>
|
|
>(Context);
|
|
var userManager = new UserManager<AppUser>(userStore,
|
|
new OptionsWrapper<IdentityOptions>(new IdentityOptions()),
|
|
new PasswordHasher<AppUser>(),
|
|
[new UserValidator<AppUser>()],
|
|
[new PasswordValidator<AppUser>()],
|
|
new UpperInvariantLookupNormalizer(),
|
|
new IdentityErrorDescriber(),
|
|
null!,
|
|
Substitute.For<ILogger<UserManager<AppUser>>>());
|
|
|
|
// Create users with the UserManager such that the SecurityStamp is set
|
|
await userManager.CreateAsync(user);
|
|
await userManager.CreateAsync(defaultAdmin);
|
|
|
|
var accountService = new AccountService(userManager, Substitute.For<ILogger<AccountService>>(), UnitOfWork, Mapper, Substitute.For<ILocalizationService>());
|
|
var oidcService = new OidcService(Substitute.For<ILogger<OidcService>>(), userManager, UnitOfWork, accountService, Substitute.For<IEmailService>());
|
|
return (oidcService, user, accountService, userManager);
|
|
}
|
|
|
|
protected override async Task ResetDb()
|
|
{
|
|
Context.AppUser.RemoveRange(Context.AppUser);
|
|
Context.Library.RemoveRange(Context.Library);
|
|
await UnitOfWork.CommitAsync();
|
|
}
|
|
}
|