Fixed a bug where fresh installs inviting a new users would get their own admin account's side nav and dashboard streams overwritten.

This commit is contained in:
Joseph Milazzo 2023-12-09 16:43:11 -06:00
parent d48e59384f
commit 63bc25f12d
3 changed files with 60 additions and 53 deletions

View file

@ -26,6 +26,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting; using Microsoft.AspNetCore.RateLimiting;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SharpCompress;
namespace API.Controllers; namespace API.Controllers;
@ -137,8 +138,7 @@ public class AccountController : BaseApiController
if (!result.Succeeded) return BadRequest(result.Errors); if (!result.Succeeded) return BadRequest(result.Errors);
// Assign default streams // Assign default streams
user.DashboardStreams = Seed.DefaultStreams.ToList(); AddDefaultStreamsToUser(user);
user.SideNavStreams = Seed.DefaultSideNavStreams.ToList();
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user); var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
if (string.IsNullOrEmpty(token)) return BadRequest(await _localizationService.Get("en", "confirm-token-gen")); if (string.IsNullOrEmpty(token)) return BadRequest(await _localizationService.Get("en", "confirm-token-gen"));
@ -595,7 +595,7 @@ public class AccountController : BaseApiController
if (string.IsNullOrEmpty(dto.Email)) if (string.IsNullOrEmpty(dto.Email))
return BadRequest(await _localizationService.Translate(userId, "invalid-payload")); return BadRequest(await _localizationService.Translate(userId, "invalid-payload"));
_logger.LogInformation("{User} is inviting {Email} to the server", adminUser.UserName, dto.Email); _logger.LogInformation("{User} is inviting {Email} to the server", User.GetUsername(), dto.Email);
// Check if there is an existing invite // Check if there is an existing invite
var emailValidationErrors = await _accountService.ValidateEmail(dto.Email); var emailValidationErrors = await _accountService.ValidateEmail(dto.Email);
@ -608,7 +608,8 @@ public class AccountController : BaseApiController
} }
// Create a new user // Create a new user
var user = new AppUserBuilder(dto.Email, dto.Email, await _unitOfWork.SiteThemeRepository.GetDefaultTheme()).Build(); var user = new AppUserBuilder(dto.Email, dto.Email,
await _unitOfWork.SiteThemeRepository.GetDefaultTheme()).Build();
_unitOfWork.UserRepository.Add(user); _unitOfWork.UserRepository.Add(user);
try try
{ {
@ -616,9 +617,7 @@ public class AccountController : BaseApiController
if (!result.Succeeded) return BadRequest(result.Errors); if (!result.Succeeded) return BadRequest(result.Errors);
// Assign default streams // Assign default streams
user.DashboardStreams = Seed.DefaultStreams.ToList(); AddDefaultStreamsToUser(user);
user.SideNavStreams = Seed.DefaultSideNavStreams.ToList();
// Assign Roles // Assign Roles
var roles = dto.Roles; var roles = dto.Roles;
@ -657,7 +656,6 @@ public class AccountController : BaseApiController
user.CreateSideNavFromLibrary(lib); user.CreateSideNavFromLibrary(lib);
} }
_unitOfWork.UserRepository.Update(user);
user.AgeRestriction = hasAdminRole ? AgeRating.NotApplicable : dto.AgeRestriction.AgeRating; user.AgeRestriction = hasAdminRole ? AgeRating.NotApplicable : dto.AgeRestriction.AgeRating;
user.AgeRestrictionIncludeUnknowns = hasAdminRole || dto.AgeRestriction.IncludeUnknowns; user.AgeRestrictionIncludeUnknowns = hasAdminRole || dto.AgeRestriction.IncludeUnknowns;
@ -669,6 +667,7 @@ public class AccountController : BaseApiController
} }
user.ConfirmationToken = token; user.ConfirmationToken = token;
_unitOfWork.UserRepository.Update(user);
await _unitOfWork.CommitAsync(); await _unitOfWork.CommitAsync();
} }
catch (Exception ex) catch (Exception ex)
@ -702,7 +701,7 @@ public class AccountController : BaseApiController
BackgroundJob.Enqueue(() => _emailService.SendConfirmationEmail(new ConfirmationEmailDto() BackgroundJob.Enqueue(() => _emailService.SendConfirmationEmail(new ConfirmationEmailDto()
{ {
EmailAddress = dto.Email, EmailAddress = dto.Email,
InvitingUser = adminUser.UserName!, InvitingUser = User.GetUsername(),
ServerConfirmationLink = emailLink ServerConfirmationLink = emailLink
})); }));
} }
@ -721,6 +720,19 @@ public class AccountController : BaseApiController
return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-invite-user")); return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-invite-user"));
} }
private void AddDefaultStreamsToUser(AppUser user)
{
foreach (var newStream in Seed.DefaultStreams.Select(stream => _mapper.Map<AppUserDashboardStream, AppUserDashboardStream>(stream)))
{
user.DashboardStreams.Add(newStream);
}
foreach (var stream in Seed.DefaultSideNavStreams.Select(stream => _mapper.Map<AppUserSideNavStream, AppUserSideNavStream>(stream)))
{
user.SideNavStreams.Add(stream);
}
}
/// <summary> /// <summary>
/// Last step in authentication flow, confirms the email token for email /// Last step in authentication flow, confirms the email token for email
/// </summary> /// </summary>

View file

@ -76,8 +76,7 @@ public static class Seed
}, },
}.ToArray()); }.ToArray());
public static readonly ImmutableArray<AppUserSideNavStream> DefaultSideNavStreams = ImmutableArray.Create(new[] public static readonly ImmutableArray<AppUserSideNavStream> DefaultSideNavStreams = ImmutableArray.Create(
{
new AppUserSideNavStream() new AppUserSideNavStream()
{ {
Name = "want-to-read", Name = "want-to-read",
@ -85,39 +84,34 @@ public static class Seed
Order = 1, Order = 1,
IsProvided = true, IsProvided = true,
Visible = true Visible = true
}, }, new AppUserSideNavStream()
new AppUserSideNavStream()
{ {
Name = "collections", Name = "collections",
StreamType = SideNavStreamType.Collections, StreamType = SideNavStreamType.Collections,
Order = 2, Order = 2,
IsProvided = true, IsProvided = true,
Visible = true Visible = true
}, }, new AppUserSideNavStream()
new AppUserSideNavStream()
{ {
Name = "reading-lists", Name = "reading-lists",
StreamType = SideNavStreamType.ReadingLists, StreamType = SideNavStreamType.ReadingLists,
Order = 3, Order = 3,
IsProvided = true, IsProvided = true,
Visible = true Visible = true
}, }, new AppUserSideNavStream()
new AppUserSideNavStream()
{ {
Name = "bookmarks", Name = "bookmarks",
StreamType = SideNavStreamType.Bookmarks, StreamType = SideNavStreamType.Bookmarks,
Order = 4, Order = 4,
IsProvided = true, IsProvided = true,
Visible = true Visible = true
}, }, new AppUserSideNavStream()
new AppUserSideNavStream()
{ {
Name = "all-series", Name = "all-series",
StreamType = SideNavStreamType.AllSeries, StreamType = SideNavStreamType.AllSeries,
Order = 5, Order = 5,
IsProvided = true, IsProvided = true,
Visible = true Visible = true
}
}); });

View file

@ -240,9 +240,10 @@ public class AutoMapperProfiles : Profile
CreateMap<AppUserSmartFilter, SmartFilterDto>(); CreateMap<AppUserSmartFilter, SmartFilterDto>();
CreateMap<AppUserDashboardStream, DashboardStreamDto>(); CreateMap<AppUserDashboardStream, DashboardStreamDto>();
// CreateMap<AppUserDashboardStream, DashboardStreamDto>()
// .ForMember(dest => dest.SmartFilterEncoded, // This is for cloning to ensure the records don't get overwritten when setting from SeedData
// opt => opt.MapFrom(src => src.SmartFilter)); CreateMap<AppUserDashboardStream, AppUserDashboardStream>();
CreateMap<AppUserSideNavStream, AppUserSideNavStream>();
} }
} }