public async Task SubmitPositiveDiagnosisAsync(SelfDiagnosisSubmissionRequest diagnosis) { using (var ctx = new ExposureNotificationContext(dbContextOptions)) using (var transaction = ctx.Database.BeginTransaction()) { // Ensure the database contains the diagnosis uid var dbDiag = await ctx.Diagnoses.FirstOrDefaultAsync(d => d.DiagnosisUid == diagnosis.DiagnosisUid); // Check that the diagnosis uid exists and that there aren't too many keys associated // already, otherwise it might be someone submitting fake data with a legitimate key if (dbDiag == null || dbDiag.KeyCount > maxKeysPerDiagnosisFile) { throw new InvalidOperationException(); } var dbKeys = diagnosis.Keys.Select(k => DbTemporaryExposureKey.FromKey(k)).ToList(); // Add the new keys to the db foreach (var dbk in dbKeys) { // Only add key if it doesn't exist already if (!await ctx.TemporaryExposureKeys.AnyAsync(k => k.Base64KeyData == dbk.Base64KeyData)) { ctx.TemporaryExposureKeys.Add(dbk); } } // Increment key count dbDiag.KeyCount += diagnosis.Keys.Count(); await ctx.SaveChangesAsync(); await transaction.CommitAsync(); } }
public async Task <KeysResponse> GetKeysAsync(ulong since, int skip = 0, int take = 1000) { using (var ctx = new ExposureNotificationContext(dbContextOptions)) { var oldest = DateTimeOffset.UtcNow.AddDays(-14).ToUnixTimeSeconds(); var results = await ctx.TemporaryExposureKeys.AsQueryable() .Where(dtk => dtk.Id > since && dtk.TimestampSecondsSinceEpoch >= oldest) .OrderBy(dtk => dtk.Id) .Skip(skip) .Take(take) .ToListAsync().ConfigureAwait(false); var newestIndex = results .LastOrDefault()?.Id; var keys = results.Select(dtk => dtk.ToKey()); return(new KeysResponse { Latest = newestIndex ?? 0, Keys = keys }); } }
public void DeleteAllKeysAsync() { using (var ctx = new ExposureNotificationContext(dbContextOptions)) { ctx.TemporaryExposureKeys.RemoveRange(ctx.TemporaryExposureKeys); ctx.SaveChanges(); } }
public Task <List <TemporaryExposureKey> > GetAllKeysAsync() { using (var ctx = new ExposureNotificationContext(dbContextOptions)) { return(ctx.TemporaryExposureKeys .Select(k => k.ToKey()) .ToListAsync()); } }
public async Task <int> GetNextBatchAsync(int batchNumber, string region, Func <TemporaryExposureKeyBatch, Task> processBatch) { region ??= DbTemporaryExposureKey.DefaultRegion; var keyCount = 0; using (var ctx = new ExposureNotificationContext(dbContextOptions)) using (var transaction = ctx.Database.BeginTransaction()) { var keys = await ctx.TemporaryExposureKeys .Where(k => k.Region == region && !k.Processed) .OrderBy(k => k.TimestampMsSinceEpoch) .Take(TemporaryExposureKeyBatches.MaxKeysPerFile) .ToListAsync(); var exposureKeys = keys.Select(k => k.ToProtoKey()); keyCount = exposureKeys.Count(); var f = new TemporaryExposureKeyBatch { Header = new TemporaryExposureKeyBatchHeader { BatchNum = batchNumber, BatchSize = keyCount, StartTimestamp = keys.First().TimestampMsSinceEpoch, EndTimestamp = keys.Last().TimestampMsSinceEpoch, Region = region } }; f.Key.AddRange(exposureKeys); await processBatch(f); // Decide to delete keys or just mark them as processed // Marking as processed is better if (Startup.DeleteKeysFromDbAfterBatching) { ctx.TemporaryExposureKeys.RemoveRange(keys); } else { foreach (var k in keys) { k.Processed = true; } } await ctx.SaveChangesAsync(); await transaction.CommitAsync(); } return(keyCount); }
public ExposureNotificationStorage( Action <DbContextOptionsBuilder> buildDbContextOpetions = null, Action <DbContext> initializeDb = null) { var dbContextOptionsBuilder = new DbContextOptionsBuilder(); buildDbContextOpetions?.Invoke(dbContextOptionsBuilder); dbContextOptions = dbContextOptionsBuilder.Options; using (var ctx = new ExposureNotificationContext(dbContextOptions)) initializeDb?.Invoke(ctx); }
public async Task AddDiagnosisUidsAsync(IEnumerable <string> diagnosisUids) { using (var ctx = new ExposureNotificationContext(dbContextOptions)) { foreach (var d in diagnosisUids) { if (!(await ctx.Diagnoses.AnyAsync(r => r.DiagnosisUid == d))) { ctx.Diagnoses.Add(new DbDiagnosis(d)); } } await ctx.SaveChangesAsync(); } }
public async Task RemoveDiagnosisUidsAsync(IEnumerable <string> diagnosisUids) { using (var ctx = new ExposureNotificationContext(dbContextOptions)) { var toRemove = new List <DbDiagnosis>(); foreach (var d in diagnosisUids) { var existingUid = await ctx.Diagnoses.FindAsync(d); if (existingUid != null) { toRemove.Add(existingUid); } } ctx.Diagnoses.RemoveRange(toRemove); await ctx.SaveChangesAsync(); } }
public async Task SubmitPositiveDiagnosisAsync(SelfDiagnosisSubmissionRequest diagnosis) { using (var ctx = new ExposureNotificationContext(dbContextOptions)) { // Ensure the database contains the diagnosis uid if (!ctx.Diagnoses.Any(d => d.DiagnosisUid == diagnosis.DiagnosisUid)) { throw new InvalidOperationException(); } var dbKeys = diagnosis.Keys.Select(k => DbTemporaryExposureKey.FromKey(k)).ToList(); foreach (var dbk in dbKeys) { ctx.TemporaryExposureKeys.Add(dbk); } await ctx.SaveChangesAsync(); } }
public Task <bool> CheckIfDiagnosisUidExistsAsync(string diagnosisUid) { using (var ctx = new ExposureNotificationContext(dbContextOptions)) return(Task.FromResult(ctx.Diagnoses.Any(d => d.DiagnosisUid.Equals(diagnosisUid)))); }