mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-06 14:42:09 +00:00
Merge remote-tracking branch 'origin/dev' into feat/ab/sh-326-team-member
# Conflicts: # Api.SeaHavenIndustries.Tests/TeamMemberServiceTests.cs # SeaHaven.DataServices/Implementation/TeamPermissionOverrideDataService.cs
This commit is contained in:
commit
8a4de283dc
3 changed files with 38 additions and 2 deletions
|
|
@ -3,6 +3,7 @@ using Data.SeaHavenIndustries;
|
||||||
using Data.SeaHavenIndustries.Enums;
|
using Data.SeaHavenIndustries.Enums;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -315,6 +316,26 @@ public sealed class TeamMemberServiceTests
|
||||||
userData.Verify(data => data.UpdateUserAsync(user, It.IsAny<CancellationToken>()), Times.Once);
|
userData.Verify(data => data.UpdateUserAsync(user, It.IsAny<CancellationToken>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Create_ConcurrentDuplicateEmail_ReturnsAlreadyInUseInsteadOf500()
|
||||||
|
{
|
||||||
|
var service = NewService(out var userManager, out var roleManager, out _, out _, out _, out _);
|
||||||
|
userManager
|
||||||
|
.Setup(manager => manager.FindByEmailAsync(It.IsAny<string>()))
|
||||||
|
.ReturnsAsync((ApplicationUser?)null);
|
||||||
|
roleManager.Setup(manager => manager.RoleExistsAsync("Dispatcher")).ReturnsAsync(true);
|
||||||
|
userManager
|
||||||
|
.Setup(manager => manager.CreateAsync(It.IsAny<ApplicationUser>()))
|
||||||
|
.ThrowsAsync(new DbUpdateException("duplicate key", new Exception()));
|
||||||
|
|
||||||
|
var result = await service.CreateAsync(ValidRequest(), Admin(), CancellationToken.None);
|
||||||
|
|
||||||
|
result.Success.Should().BeFalse();
|
||||||
|
result.Error.Should().Be("Email is already in use.");
|
||||||
|
userManager.Verify(manager => manager.AddToRoleAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>()), Times.Never);
|
||||||
|
userManager.Verify(manager => manager.DeleteAsync(It.IsAny<ApplicationUser>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
private static TeamMemberService NewService(
|
private static TeamMemberService NewService(
|
||||||
out Mock<UserManager<ApplicationUser>> userManager,
|
out Mock<UserManager<ApplicationUser>> userManager,
|
||||||
out Mock<RoleManager<IdentityRole>> roleManager,
|
out Mock<RoleManager<IdentityRole>> roleManager,
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,8 @@ public sealed class TeamPermissionOverrideDataService : ITeamPermissionOverrideD
|
||||||
}
|
}
|
||||||
catch (DbUpdateException)
|
catch (DbUpdateException)
|
||||||
{
|
{
|
||||||
// A concurrent PUT inserted the same composite key between the read and save.
|
// A concurrent write (create or PUT) inserted the same composite key
|
||||||
|
// between our existence check and this save. Converge on the caller's intent.
|
||||||
_context.Entry(addition).State = EntityState.Detached;
|
_context.Entry(addition).State = EntityState.Detached;
|
||||||
var winner = await _context.UserPermissionOverrides
|
var winner = await _context.UserPermissionOverrides
|
||||||
.SingleAsync(
|
.SingleAsync(
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using System.Security.Claims;
|
||||||
using Data.SeaHavenIndustries;
|
using Data.SeaHavenIndustries;
|
||||||
using Data.SeaHavenIndustries.Enums;
|
using Data.SeaHavenIndustries.Enums;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using SeaHaven.DataServices.Interfaces;
|
using SeaHaven.DataServices.Interfaces;
|
||||||
using SeaHaven.Services.Constants;
|
using SeaHaven.Services.Constants;
|
||||||
using SeaHaven.Services.DTOs;
|
using SeaHaven.Services.DTOs;
|
||||||
|
|
@ -71,7 +72,20 @@ public sealed class TeamMemberService : ITeamMemberService
|
||||||
PendingRegistrationCreatedDate = now
|
PendingRegistrationCreatedDate = now
|
||||||
};
|
};
|
||||||
|
|
||||||
var createResult = await _userManager.CreateAsync(user);
|
IdentityResult createResult;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
createResult = await _userManager.CreateAsync(user);
|
||||||
|
}
|
||||||
|
catch (DbUpdateException)
|
||||||
|
{
|
||||||
|
// A concurrent create won the race on the unique user-name index
|
||||||
|
// between the FindByEmailAsync check above and this insert. Surface
|
||||||
|
// the same conflict message instead of letting the database
|
||||||
|
// exception bubble up as a 500.
|
||||||
|
return Failure("Email is already in use.");
|
||||||
|
}
|
||||||
|
|
||||||
if (!createResult.Succeeded)
|
if (!createResult.Succeeded)
|
||||||
return Failure(createResult.Errors.FirstOrDefault()?.Description ?? "Unable to create team member.");
|
return Failure(createResult.Errors.FirstOrDefault()?.Description ?? "Unable to create team member.");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue