Skip to content

Commit

Permalink
Make minor development updates (#135)
Browse files Browse the repository at this point in the history
* Update App Library NuGet package

* Output DB setup commands during development

* Fix minor issue when logging in local user

* Avoid logging email, even masked

Fix code scanning alert: Exposure of private information

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
  • Loading branch information
1 parent 4484a54 commit 4a81de6
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 54 deletions.
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<PackageVersion Include="ClosedXML" Version="0.104.1" />
<PackageVersion Include="Dapper" Version="2.1.35" />
<PackageVersion Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageVersion Include="GaEpd.AppLibrary" Version="5.3.1" />
<PackageVersion Include="GaEpd.AppLibrary" Version="5.4.0" />
<PackageVersion Include="GaEpd.EmailService" Version="1.0.0" />
<PackageVersion Include="GaEpd.FileService" Version="3.1.1" />
<PackageVersion Include="HtmlSanitizer" Version="8.1.870" />
Expand Down
46 changes: 21 additions & 25 deletions src/WebApp/Pages/Account/ExternalLogin.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using MyApp.AppServices.Staff.Dto;
using MyApp.Domain.Identity;
using MyApp.WebApp.Models;
using MyApp.WebApp.Platform.Logging;
using MyApp.WebApp.Platform.PageModelHelpers;
using MyApp.WebApp.Platform.Settings;

Expand Down Expand Up @@ -67,7 +66,9 @@ private async Task<IActionResult> SignInAsLocalUser()
var user = await userManager.FindByIdAsync(staffId);
logger.LogInformation("Local user with ID {StaffId} signed in", staffId);

await signInManager.SignInAsync(user!, false);
user!.MostRecentLogin = DateTimeOffset.Now;
await userManager.UpdateAsync(user);
await signInManager.SignInAsync(user, false);
return LocalRedirectOrHome();
}

Expand All @@ -92,19 +93,19 @@ public async Task<IActionResult> OnGetCallbackAsync(string? returnUrl = null, st

if (!userEmail.IsValidEmailDomain())
{
logger.LogWarning("User {UserName} with invalid email domain attempted signin", userEmail.MaskEmail());
logger.LogWarning("User with invalid email domain attempted signin");
return RedirectToPage("./Unavailable");
}

logger.LogInformation("User {UserName} in tenant {TenantID} successfully authenticated", userEmail.MaskEmail(),
userTenant);
logger.LogInformation("User with object ID {ObjectId} in tenant {TenantID} successfully authenticated",
externalLoginInfo.Principal.GetObjectId(), userTenant);

// Determine if a user account already exists with the Object ID.
// If not, then determine if a user account already exists with the given username.
var user = AppSettings.DevSettings.UseInMemoryData
? await userManager.FindByNameAsync(userEmail)
: await userManager.Users.SingleOrDefaultAsync(u =>
u.ObjectIdentifier == externalLoginInfo.Principal.GetObjectId()) ??
: await userManager.Users.SingleOrDefaultAsync(au =>
au.ObjectIdentifier == externalLoginInfo.Principal.GetObjectId()) ??
await userManager.FindByNameAsync(userEmail);

// If the user does not have a local account yet, then create one and sign in.
Expand All @@ -114,7 +115,7 @@ public async Task<IActionResult> OnGetCallbackAsync(string? returnUrl = null, st
// If user has been marked as inactive, don't sign in.
if (!user.Active)
{
logger.LogWarning("Inactive user {Email} attempted signin", userEmail.MaskEmail());
logger.LogWarning("Inactive user with object ID {ObjectId} attempted signin", user.ObjectIdentifier);
return RedirectToPage("./Unavailable");
}

Expand Down Expand Up @@ -163,25 +164,24 @@ private async Task<IActionResult> CreateUserAndSignInAsync(ExternalLoginInfo inf
var createUserResult = await userManager.CreateAsync(user);
if (!createUserResult.Succeeded)
{
logger.LogWarning("Failed to create new user {UserName}", user.Email.MaskEmail());
logger.LogWarning("Failed to create new user with object ID {ObjectId}", user.ObjectIdentifier);
return await FailedLoginAsync(createUserResult, user);
}

logger.LogInformation("Created new user {Email} with object ID {ObjectId}", user.Email.MaskEmail(),
user.ObjectIdentifier);
logger.LogInformation("Created new user with object ID {ObjectId}", user.ObjectIdentifier);

// Add new user to application Roles if seeded in app settings or local admin user setting is enabled.
var seedAdminUsers = configuration.GetSection("SeedAdminUsers").Get<string[]>();
if (AppSettings.DevSettings.LocalUserIsStaff)
{
logger.LogInformation("Seeding staff role for new user {Email}", user.Email.MaskEmail());
logger.LogInformation("Seeding staff role for new user with object ID {ObjectId}", user.ObjectIdentifier);
await userManager.AddToRoleAsync(user, RoleName.Staff);
}

if (AppSettings.DevSettings.LocalUserIsAdmin ||
(seedAdminUsers != null && seedAdminUsers.Contains(user.Email, StringComparer.InvariantCultureIgnoreCase)))
{
logger.LogInformation("Seeding all roles for new user {Email}", user.Email.MaskEmail());
logger.LogInformation("Seeding all roles for new user with object ID {ObjectId}", user.ObjectIdentifier);
foreach (var role in AppRole.AllRoles) await userManager.AddToRoleAsync(user, role.Key);
}

Expand All @@ -194,8 +194,8 @@ private async Task<IActionResult> CreateUserAndSignInAsync(ExternalLoginInfo inf
// Update local store with from external provider.
private async Task<IActionResult> RefreshUserInfoAndSignInAsync(ApplicationUser user, ExternalLoginInfo info)
{
logger.LogInformation("Existing user {Email} logged in with {LoginProvider} provider",
user.Email.MaskEmail(), info.LoginProvider);
logger.LogInformation("Existing user with object ID {ObjectId} logged in with {LoginProvider} provider",
user.ObjectIdentifier, info.LoginProvider);

var previousValues = new ApplicationUser
{
Expand All @@ -218,7 +218,6 @@ private async Task<IActionResult> RefreshUserInfoAndSignInAsync(ApplicationUser
}

await userManager.UpdateAsync(user);

await signInManager.RefreshSignInAsync(user);
return LocalRedirectOrHome();
}
Expand All @@ -231,17 +230,17 @@ private async Task<IActionResult> AddLoginProviderAndSignInAsync(

if (!addLoginResult.Succeeded)
{
logger.LogWarning("Failed to add login provider {LoginProvider} for user {Email}",
info.LoginProvider, user.Email.MaskEmail());
logger.LogWarning("Failed to add login provider {LoginProvider} for user with object ID {ObjectId}",
info.LoginProvider, user.ObjectIdentifier);
return await FailedLoginAsync(addLoginResult, user);
}

user.ObjectIdentifier ??= info.Principal.GetObjectId();
user.MostRecentLogin = DateTimeOffset.Now;
await userManager.UpdateAsync(user);

logger.LogInformation("Login provider {LoginProvider} added for user {Email} with object ID {ObjectId}",
info.LoginProvider, user.Email.MaskEmail(), user.ObjectIdentifier);
logger.LogInformation("Login provider {LoginProvider} added for user with object ID {ObjectId}",
info.LoginProvider, user.ObjectIdentifier);

// Include the access token in the properties.
var props = new AuthenticationProperties();
Expand All @@ -262,9 +261,6 @@ private async Task<PageResult> FailedLoginAsync(IdentityResult result, Applicati
return Page();
}

private IActionResult LocalRedirectOrHome()
{
if (ReturnUrl is null) return RedirectToPage("/Staff/Index");
return LocalRedirect(ReturnUrl);
}
private IActionResult LocalRedirectOrHome() =>
ReturnUrl is null ? RedirectToPage("/Staff/Index") : LocalRedirect(ReturnUrl);
}
15 changes: 10 additions & 5 deletions src/WebApp/Platform/AppConfiguration/MigratorHostedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@ public async Task StartAsync(CancellationToken cancellationToken)
if (AppSettings.DevSettings.UseInMemoryData) return;

var migrationConnectionString = configuration.GetConnectionString("MigrationConnection");
var migrationOptions = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlServer(migrationConnectionString, builder => builder.MigrationsAssembly("EfRepository")).Options;
var dbContextOptionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlServer(migrationConnectionString, builder => builder.MigrationsAssembly("EfRepository"));

await using var migrationContext = new AppDbContext(migrationOptions);
if (AppSettings.DevSettings.UseDevSettings)
{
dbContextOptionsBuilder
.LogTo(Console.WriteLine, [DbLoggerCategory.Database.Command.Name], LogLevel.Information);
}

await using var migrationContext = new AppDbContext(dbContextOptionsBuilder.Options);

if (AppSettings.DevSettings.UseEfMigrations)
{
Expand All @@ -31,8 +37,7 @@ public async Task StartAsync(CancellationToken cancellationToken)
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
foreach (var role in AppRole.AllRoles.Keys)
{
if (!await migrationContext.Roles.AnyAsync(identityRole => identityRole.Name == role,
cancellationToken))
if (!await migrationContext.Roles.AnyAsync(idRole => idRole.Name == role, cancellationToken))
{
await roleManager.CreateAsync(new IdentityRole(role));
}
Expand Down
20 changes: 0 additions & 20 deletions src/WebApp/Platform/Logging/Redaction.cs

This file was deleted.

9 changes: 6 additions & 3 deletions tests/EfRepositoryTests/RepositoryHelper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GaEpd.AppLibrary.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using MyApp.Domain.Entities.EntryTypes;
using MyApp.Domain.Entities.Offices;
using MyApp.Domain.Entities.WorkEntries;
Expand All @@ -26,7 +27,7 @@ namespace EfRepositoryTests;
/// </summary>
public sealed class RepositoryHelper : IDisposable, IAsyncDisposable
{
private AppDbContext Context { get; set; } = default!;
private AppDbContext Context { get; set; } = null!;

private readonly DbContextOptions<AppDbContext> _options;
private readonly AppDbContext _context;
Expand All @@ -36,7 +37,8 @@ public sealed class RepositoryHelper : IDisposable, IAsyncDisposable
/// </summary>
private RepositoryHelper()
{
_options = SqliteInMemory.CreateOptions<AppDbContext>();
_options = SqliteInMemory.CreateOptions<AppDbContext>(builder =>
builder.LogTo(Console.WriteLine, events: [RelationalEventId.CommandExecuted]));
_context = new AppDbContext(_options);
_context.Database.EnsureCreated();
}
Expand All @@ -49,7 +51,8 @@ private RepositoryHelper()
private RepositoryHelper(object callingClass, string callingMember)
{
_options = callingClass.CreateUniqueMethodOptions<AppDbContext>(callingMember: callingMember,
builder: opts => opts.UseSqlServer());
builder: builder => builder.UseSqlServer()
.LogTo(Console.WriteLine, events: [RelationalEventId.CommandExecuted]));
_context = new AppDbContext(_options);
_context.Database.EnsureClean();
}
Expand Down

0 comments on commit 4a81de6

Please sign in to comment.