Fix dev-login role switching, distinct users, and user resolution races

Dev-login now updates the role when an existing user logs in as a
different role. Each dev role maps to a distinct email/name so
sessions don't collide. CognitoSub is deterministic (email-based)
to prevent mismatch between dev-login and CurrentUserService.
CurrentUserService catches DbUpdateException on concurrent user
creation and retries the lookup instead of crashing.
This commit is contained in:
Adam Moussa 2026-05-20 17:24:01 -04:00
parent f44caba906
commit f37c2aa3f0
3 changed files with 25 additions and 3 deletions

View file

@ -107,7 +107,7 @@ public class AuthController : ControllerBase
user = new User
{
Id = Guid.NewGuid(),
CognitoSub = $"dev-{Guid.NewGuid():N}",
CognitoSub = $"dev-{request.Email}",
Email = request.Email,
DisplayName = request.DisplayName ?? request.Email.Split('@')[0],
Role = role,
@ -118,6 +118,12 @@ public class AuthController : ControllerBase
_db.Users.Add(user);
await _db.SaveChangesAsync(ct);
}
else if (user.Role != role)
{
user.Role = role;
user.UpdatedAt = DateTime.UtcNow;
await _db.SaveChangesAsync(ct);
}
var claims = new List<Claim>
{

View file

@ -80,7 +80,16 @@ public class CurrentUserService : ICurrentUserService
};
_db.Users.Add(_cachedUser);
await _db.SaveChangesAsync();
try
{
await _db.SaveChangesAsync();
}
catch (DbUpdateException)
{
_db.Entry(_cachedUser).State = EntityState.Detached;
_cachedUser = await _db.Users.FirstOrDefaultAsync(u => u.Email == email)
?? throw new UnauthorizedAccessException("Could not resolve current user");
}
}
private User GetOrThrow()

View file

@ -39,10 +39,17 @@ export default function LoginPage() {
}
}, [isAuthenticated, navigate]);
const devUsers: Record<string, { email: string; name: string }> = {
SysAdmin: { email: 'adam@seahavenind.com', name: 'Adam Moussa' },
Admin: { email: 'sarah@seahavenind.com', name: 'Sarah Chen' },
Dispatcher: { email: 'mike@seahavenind.com', name: 'Mike Torres' },
};
const handleDevLogin = async (role: string) => {
setLoading(true);
try {
const user = await authApi.devLogin('adam@seahavenind.com', 'Adam Moussa', role);
const { email, name } = devUsers[role] ?? devUsers.SysAdmin;
const user = await authApi.devLogin(email, name, role);
dispatch(setUser(user));
navigate('/', { replace: true });
} catch (err) {