feat(email): export send attempt metadata
Add content-free provider delivery history to encrypted and daily owner exports, exclude payload hashes, and lock in tenant-safe hard-delete cascades.
This commit is contained in:
@@ -58,6 +58,22 @@ public sealed class EmailSendAttemptStoreTests
|
||||
property.Name.Contains("Recipient", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Hard_job_deletion_cascades_only_that_jobs_attempts()
|
||||
{
|
||||
await using var fixture = await Fixture.CreateAsync();
|
||||
var ownerOne = fixture.Store("user-1");
|
||||
var ownerTwo = fixture.Store("user-2");
|
||||
var mine = await ownerOne.CreateAsync(new(fixture.JobId, "gmail", Guid.NewGuid().ToString(), Hash('3')), default);
|
||||
var theirs = await ownerTwo.CreateAsync(new(fixture.OtherJobId, "microsoft", Guid.NewGuid().ToString(), Hash('4')), default);
|
||||
|
||||
await fixture.HardDeleteJobAsync("user-1", fixture.JobId);
|
||||
|
||||
Assert.Null(await ownerOne.GetAsync(mine.Attempt.Id, default));
|
||||
Assert.NotNull(await ownerTwo.GetAsync(theirs.Attempt.Id, default));
|
||||
Assert.Equal(1, await fixture.AttemptCountIgnoringFiltersAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Restart_recovery_is_tenant_visible_idempotent_and_never_requeues_delivery()
|
||||
{
|
||||
@@ -139,6 +155,20 @@ public sealed class EmailSendAttemptStoreTests
|
||||
return new UserNotificationStore(db, Time);
|
||||
}
|
||||
|
||||
public async Task HardDeleteJobAsync(string userId, int jobId)
|
||||
{
|
||||
await using var db = CreateDb(options, userId);
|
||||
var job = await db.JobApplications.SingleAsync(item => item.Id == jobId);
|
||||
db.JobApplications.Remove(job);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<int> AttemptCountIgnoringFiltersAsync()
|
||||
{
|
||||
await using var db = CreateDb(options, null);
|
||||
return await db.EmailSendAttempts.IgnoreQueryFilters().CountAsync();
|
||||
}
|
||||
|
||||
private static JobTrackerContext CreateDb(DbContextOptions<JobTrackerContext> options, string? userId)
|
||||
{
|
||||
var currentUser = new Mock<ICurrentUserService>();
|
||||
|
||||
Reference in New Issue
Block a user