public void Execute(string[] _) { using var tx = _WorkflowDb.BeginTransaction(); ForceWorkflowAuth(); _WorkflowDb.SaveAndCommit(); }
public async Task <EnrollmentResponse> Execute() { var validDate = _DateTimeProvider.Now().AddDays(1); //TODO smells like a setting var entity = new KeyReleaseWorkflowState { LabConfirmationId = _NumberGenerator.GenerateToken(), Created = _DateTimeProvider.Now(), BucketId = Convert.ToBase64String(_NumberGenerator.GenerateKey()), ConfirmationKey = Convert.ToBase64String(_NumberGenerator.GenerateKey()), ValidUntil = new DateTime(validDate.Year, validDate.Month, validDate.Day, 4, 0, 0, DateTimeKind.Local) //TODO smells like a setting }; _Logger.LogDebug("Writing."); await _DbContextProvider.KeyReleaseWorkflowStates.AddAsync(entity); _Logger.LogDebug("Committing."); _DbContextProvider.SaveAndCommit(); _Logger.LogDebug("Committed."); return(new EnrollmentResponse { ConfirmationKey = entity.ConfirmationKey, BucketId = entity.BucketId, LabConfirmationId = $"{entity.LabConfirmationId.Substring(0, 3)}-{entity.LabConfirmationId.Substring(3, 3)}", //TODO UI concern in DB! Validity = (long)(entity.ValidUntil - _DateTimeProvider.Now()).TotalSeconds }); }
private bool WriteAttempt(TekReleaseWorkflowStateEntity wf) { if (++_AttemptCount > AttemptCountMax) { throw new InvalidOperationException("Maximum attempts reached."); } if (_AttemptCount > 1) { _Logger.LogWarning("Duplicate PollToken found - attempt:{AttemptCount}", _AttemptCount); } wf.PollToken = _PollTokenService.Next(); try { _WorkflowDb.SaveAndCommit(); _Logger.LogDebug("Committed."); return(true); } catch (DbUpdateException ex) { if (CanRetry(ex)) { return(false); } throw; } }
private bool WriteAttempt(TekReleaseWorkflowStateEntity item) { if (++_AttemptCount > AttemptCountMax) { _Logger.WriteMaximumCreateAttemptsReached(); throw new InvalidOperationException("Maximum create attempts reached."); } if (_AttemptCount > 1) { _Logger.WriteDuplicatesFound(_AttemptCount); } item.LabConfirmationId = _LabConfirmationIdService.Next(); item.BucketId = _NumberGenerator.NextByteArray(_WorkflowConfig.BucketIdLength); item.ConfirmationKey = _NumberGenerator.NextByteArray(_WorkflowConfig.ConfirmationKeyLength); try { _WorkflowDbContext.SaveAndCommit(); _Logger.WriteCommitted(); return(true); } catch (DbUpdateException ex) { _WorkflowDbContext.Remove(item); if (CanRetry(ex)) { return(false); } throw; } }
private bool WriteAttempt(TekReleaseWorkflowStateEntity wf) { if (++_attemptCount > AttemptCountMax) { throw new InvalidOperationException("Maximum attempts reached."); } if (_attemptCount > 1) { _logger.WriteDuplicatePollTokenFound(_attemptCount); } wf.PollToken = _pollTokenService.Next(); try { _workflowDb.SaveAndCommit(); _logger.WritePollTokenCommit(); return(true); } catch (DbUpdateException ex) { if (CanRetry(ex)) { return(false); } throw; } }
public async Task <LabVerifyAuthorisationResponse> Execute(LabVerifyArgs args) { if (!_PollTokens.Validate(args.PollToken)) { throw new ArgumentException("Not valid.", nameof(args)); } var wf = await _DbContextProvider.KeyReleaseWorkflowStates .Include(x => x.Keys) .FirstOrDefaultAsync(state => state.PollToken == args.PollToken); if (wf == null) { var message = $"KeyReleaseWorkflowState not found - PollToken:{args.PollToken}."; _Logger.LogError(message); return(new LabVerifyAuthorisationResponse { Error = "Workflow not found.", Valid = false }); } var refreshedToken = _PollTokens.GenerateToken(); wf.PollToken = refreshedToken; _Logger.LogDebug($"Committing."); _DbContextProvider.SaveAndCommit(); _Logger.LogInformation($"Committed - new PollToken:{wf.PollToken}."); return(new LabVerifyAuthorisationResponse { PollToken = refreshedToken, Valid = wf.Keys?.Any() ?? false }); }
private async Task InnerExecute(byte[] signature, HttpRequest request) { try { if (signature == null) { _Logger.LogError("Signature error: null."); return; } if (signature.Length == 0) { _Logger.LogError("Signature error: Zero length."); return; } using var reader = new StreamReader(request.Body); var payload = await reader.ReadToEndAsync(); var args = _JsonSerializer.Deserialize <ReleaseTeksArgs>(payload); _Logger.LogDebug($"Body: {args}."); var workflow = _DbContextProvider .KeyReleaseWorkflowStates .FirstOrDefault(x => x.BucketId == args.BucketId); if (workflow == null) { _Logger.LogError("Matching workflow not found."); return; } _Logger.LogDebug("Matching workflow found."); if (!_KeyValidator.Validate(args, workflow)) { _Logger.LogError("Keys not valid."); return; } if (!_SignatureValidator.Valid(signature, workflow, Encoding.UTF8.GetBytes(payload))) { _Logger.LogError($"Signature not valid: {Convert.ToBase64String(signature)}."); return; } _Logger.LogDebug("Writing."); await _Writer.Execute(args); _Logger.LogDebug("Committing."); _DbContextProvider.SaveAndCommit(); _Logger.LogDebug("Committed."); } catch (Exception e) { _Logger.LogError(e.ToString()); } }
public async Task <IActionResult> Execute(AuthorisationArgs args) { await _AuthorisationWriter.Execute(args); _DbContextProvider.SaveAndCommit(); return(new OkObjectResult(new AuthorisationResponse { Valid = true })); }
private async Task GenWorkflows() { for (var i = 0; i < _Args.WorkflowCount; i++) { _WorkflowDb.BeginTransaction(); var workflow = await _RegisterWriter().Execute(); //Save/Commit _WorkflowDb.BeginTransaction(); GenTeks(workflow); _WorkflowDb.SaveAndCommit(); } }
public async Task <IActionResult> Execute(KeysLastAuthorisationArgs args) { if (!_Validator.Valid(args.UploadAuthorisationToken)) //TODO check validation { return(new OkResult()); } await _AuthorisationWriter.Execute(args); _DbContextProvider.SaveAndCommit(); return(new OkResult()); }
public async Task <IActionResult> Execute() { var entityType = _DbContextProvider.Model.FindEntityType(typeof(KeyReleaseWorkflowState)); var schema = entityType.GetSchema(); var tableName = entityType.GetTableName(); var query = $"DELETE FROM [{schema}].[{tableName}] WHERE {nameof(KeyReleaseWorkflowState.ValidUntil)} <= GETDATE()"; await _DbContextProvider.Database.ExecuteSqlRawAsync(query); _DbContextProvider.SaveAndCommit(); return(new OkObjectResult(true)); }
public async Task <IActionResult> Execute(byte[] signature, string payload) { var args = JsonConvert.DeserializeObject <KeysLastReleaseTeksArgs>(payload); if (!_KeyValidator.Validate(args) || !_SignatureValidator.Valid(signature, args.BucketId, Encoding.UTF8.GetBytes(payload))) { return(new OkResult()); } await _Writer.Execute(args); _DbContextProvider.SaveAndCommit(); return(new OkResult()); }
public void Execute() { var expired = _DateTimeProvider.Now() - TimeSpan.FromMinutes(_KeysLastWorkflowConfig.AuthorisationWindowDurationMinutes); _DbContextProvider.BeginTransaction(); throw new NotImplementedException(); //var q = _DbContextProvider.KeysLastWorkflows // .Where(x => x.State == KeysLastWorkflowState.Receiving && x.AuthorisationWindowStart < expired); //_DbContextProvider.KeysLastWorkflows.RemoveRange(q); _DbContextProvider.SaveChanges(); _DbContextProvider.SaveAndCommit(); }
public void Execute() { var expired = _DateTimeProvider.Now() - TimeSpan.FromDays(_KeysLastWorkflowConfig.SecretLifetimeDays); _DbContextProvider.BeginTransaction(); throw new NotImplementedException(); //var q = _DbContextProvider.KeysLastWorkflows // .Where(x => x.State == KeysLastWorkflowState.Unauthorised && x.Created < expired); //_DbContextProvider.KeysLastWorkflows.RemoveRange(q); _DbContextProvider.SaveChanges(); _DbContextProvider.SaveAndCommit(); }
public async Task <IActionResult> Execute(KeysFirstEscrowArgs args) { if (!_KeysFirstEscrowValidator.Validate(args)) { return(new BadRequestResult()); } await using (var tx = _DbContextProvider.BeginTransaction()) { await _KeysFirstEscrowDbInsertCommand.Execute(args); _DbContextProvider.SaveAndCommit(); } return(new OkResult()); }
public async Task AddExampleContent() { var r = new Random(); await using var tx = await _Provider.Database.BeginTransactionAsync(); var wfs1 = new KeyReleaseWorkflowState { LabConfirmationId = "2L2587", BucketId = "2", ConfirmationKey = "3", Created = new DateTime(2020, 5, 1), }; var key1 = new TemporaryExposureKeyEntity { Owner = wfs1, PublishingState = PublishingState.Unpublished, RollingPeriod = 1, RollingStartNumber = 1, TransmissionRiskLevel = 0, KeyData = new byte[16], Region = "NL" }; r.NextBytes(key1.KeyData); var key2 = new TemporaryExposureKeyEntity { Owner = wfs1, PublishingState = PublishingState.Unpublished, RollingPeriod = 1, RollingStartNumber = 1, TransmissionRiskLevel = 0, KeyData = new byte[16], Region = "NL" }; r.NextBytes(key1.KeyData); await _Provider.KeyReleaseWorkflowStates.AddAsync(wfs1); await _Provider.TemporaryExposureKeys.AddRangeAsync(key1, key2); _Provider.SaveAndCommit(); }
public async Task Execute(int pAuthorize, Random r) { _DbContextProvider.BeginTransaction(); var unauthorized = _DbContextProvider.Set <KeyReleaseWorkflowState>() .Where(x => x.Authorised == false) .Select(x => x.ConfirmationKey) .ToArray(); var authorized = unauthorized .Where(x => r.Next(100) <= pAuthorize); foreach (var i in authorized) { await _Writer.Execute(new KeysFirstAuthorisationArgs { Token = i }); } _DbContextProvider.SaveAndCommit(); }
public async Task AddExampleContent() { var r2 = new StandardRandomNumberGenerator(); await using var tx = await _Provider.Database.BeginTransactionAsync(); var wfs1 = new TekReleaseWorkflowStateEntity { LabConfirmationId = _LabConfirmationIdService.Next(), BucketId = r2.NextByteArray(_WorkflowConfig.BucketIdLength), ConfirmationKey = r2.NextByteArray(_WorkflowConfig.ConfirmationKeyLength), Created = new DateTime(2020, 5, 1, 0, 0, 0, DateTimeKind.Utc), }; var key1 = new TekEntity { Owner = wfs1, PublishingState = PublishingState.Unpublished, RollingPeriod = 2, RollingStartNumber = DateTime.UtcNow.Date.ToRollingStartNumber(), KeyData = r2.NextByteArray(_TekValidatorConfig.KeyDataLength), Region = "NL" }; var key2 = new TekEntity { Owner = wfs1, PublishingState = PublishingState.Unpublished, RollingPeriod = 144, RollingStartNumber = DateTime.UtcNow.Date.ToRollingStartNumber(), KeyData = r2.NextByteArray(_TekValidatorConfig.KeyDataLength), Region = "NL" }; await _Provider.KeyReleaseWorkflowStates.AddAsync(wfs1); await _Provider.TemporaryExposureKeys.AddRangeAsync(key1, key2); _Provider.SaveAndCommit(); }
public async Task Execute(byte[] signature, HttpRequest request) { using var reader = new StreamReader(request.Body); var payload = await reader.ReadToEndAsync(); var args = JsonConvert.DeserializeObject <ReleaseTeksArgs>(payload); var workflow = _DbContextProvider .KeyReleaseWorkflowStates .FirstOrDefault(x => x.BucketId == args.BucketId); if (workflow == null || !_KeyValidator.Validate(args, workflow) || !_SignatureValidator.Valid(signature, workflow, Encoding.UTF8.GetBytes(payload))) { return; } await _Writer.Execute(args); _DbContextProvider.SaveAndCommit(); }
private bool TryGenerateRemainingFieldsAndWriteToDb(TekReleaseWorkflowStateEntity item) { if (++_AttemptCount > AttemptCountMax) { _logger.WriteMaximumCreateAttemptsReached(); throw new InvalidOperationException("Maximum create attempts reached."); } if (_AttemptCount > 1) { _logger.WriteDuplicatesFound(_AttemptCount); } item.GGDKey = _luhnModNGenerator.Next(_luhnModNConfig.ValueLength); item.BucketId = _numberGenerator.NextByteArray(UniversalConstants.BucketIdByteCount); item.ConfirmationKey = _numberGenerator.NextByteArray(UniversalConstants.ConfirmationKeyByteCount); try { _workflowDbContext.SaveAndCommit(); _logger.WriteCommitted(); return(true); } catch (DbUpdateException ex) { _workflowDbContext.Database.CurrentTransaction.RollbackAsync(); _workflowDbContext.Remove(item); if (CanRetry(ex)) { return(false); } throw; } }
public async Task <EnrollmentResponse> Execute() { var entity = new KeyReleaseWorkflowState { LabConfirmationId = _NumberGenerator.GenerateToken(), Created = _DateTimeProvider.Now(), BucketId = Convert.ToBase64String(_NumberGenerator.GenerateKey()), ConfirmationKey = Convert.ToBase64String(_NumberGenerator.GenerateKey()), }; await _DbContextProvider.KeyReleaseWorkflowStates.AddAsync(entity); _DbContextProvider.SaveAndCommit(); var validDate = DateTime.Now.AddDays(1); return(new EnrollmentResponse { ConfirmationKey = entity.ConfirmationKey, BucketId = entity.BucketId, LabConfirmationId = entity.LabConfirmationId, ValidUntil = new DateTime(validDate.Year, validDate.Month, validDate.Day, 4, 0, 0, DateTimeKind.Local) }); }
private async Task InnerExecute(byte[] signature, byte[] body) { _BodyBytes = body; if ((signature?.Length ?? 0) != _WorkflowConfig.PostKeysSignatureLength) { _Logger.WriteSignatureValidationFailed(); return; } try { var argsJson = Encoding.UTF8.GetString(_BodyBytes); _ArgsObject = _JsonSerializer.Deserialize <PostTeksArgs>(argsJson); } catch (Exception e) { _Logger.WritePostBodyParsingFailed(e); return; } var base64Parser = new Base64(); var base64ParserResult = base64Parser.TryParseAndValidate(_ArgsObject.BucketId, _WorkflowConfig.BucketIdLength); if (!base64ParserResult.Valid) { _Logger.WriteBucketIdParsingFailed(_ArgsObject.BucketId, base64ParserResult.Messages); return; } _BucketIdBytes = base64ParserResult.Item; var messages = _KeyValidator.Validate(_ArgsObject); if (messages.Length > 0) { _Logger.WriteTekValidationFailed(messages); return; } var teks = _ArgsObject.Keys.Select(Mapper.MapToTek).ToArray(); foreach (var i in teks) { i.PublishAfter = _DateTimeProvider.Snapshot; } messages = new TekListDuplicateValidator().Validate(teks); if (messages.Length > 0) { _Logger.WriteTekDuplicatesFound(messages); return; } //Validation ends, filtering starts var filterResult = _TekApplicableWindowFilter.Execute(teks); _Logger.WriteApplicableWindowFilterResult(filterResult.Messages); teks = filterResult.Items; _Logger.WriteValidTekCount(teks.Length); var workflow = _DbContext .KeyReleaseWorkflowStates .Include(x => x.Teks) .SingleOrDefault(x => x.BucketId == _BucketIdBytes); if (workflow == null) { _Logger.WriteBucketDoesNotExist(_ArgsObject.BucketId); return; } if (!_SignatureValidator.Valid(signature, workflow.ConfirmationKey, _BodyBytes)) { _Logger.WriteSignatureInvalid(workflow.BucketId, signature); return; } var filterResults = _TekListWorkflowFilter.Filter(teks, workflow); _Logger.WriteWorkflowFilterResults(filterResults.Messages); _Logger.WriteValidTekCountSecondPass(teks.Length); //Run after the filter removes the existing TEKs from the args. var allTeks = workflow.Teks.Select(Mapper.MapToTek).Concat(filterResults.Items).ToArray(); messages = new TekListDuplicateKeyDataValidator().Validate(allTeks); if (messages.Length > 0) { _Logger.WriteTekDuplicatesFoundWholeWorkflow(messages); return; } _Logger.WriteDbWriteStart(); var writeArgs = new TekWriteArgs { WorkflowStateEntityEntity = workflow, NewItems = filterResults.Items }; await _Writer.Execute(writeArgs); _DbContext.SaveAndCommit(); _Logger.WriteDbWriteCommitted(); if (filterResults.Items.Length != 0) { _Logger.WriteTekCountAdded(filterResults.Items.Length); } }
private async Task CommitResults() { _Logger.LogInformation($"Commit results - publish EKSs."); await using (_PublishingDbContext.BeginTransaction()) { var move = _PublishingDbContext.Set <EksCreateJobOutputEntity>().Select( x => new ExposureKeySetContentEntity { Created = _Start, Release = x.Release, ContentTypeName = MediaTypeNames.Application.Zip, Content = x.Content, CreatingJobName = x.CreatingJobName, CreatingJobQualifier = x.CreatingJobQualifier, PublishingId = _PublishingId.Create(x.Content) }).ToArray(); await using (_ContentDbContext.BeginTransaction()) { _ContentDbContext.Set <ExposureKeySetContentEntity>().AddRange(move); _ContentDbContext.SaveAndCommit(); } } _Logger.LogInformation($"Commit results - Mark TEKs as Published."); await using (_PublishingDbContext.BeginTransaction()) //Read-only { await using (_WorkflowDbContext.BeginTransaction()) { var count = 0; var used = _PublishingDbContext.Set <EksCreateJobInputEntity>() .Where(x => x.Used) .Skip(count) .Select(x => x.Id) .Take(100) .ToArray(); while (used.Length > 0) { var zap = _WorkflowDbContext.TemporaryExposureKeys .Where(x => used.Contains(x.Id)) .ToList(); foreach (var i in zap) { i.PublishingState = PublishingState.Published; } await _WorkflowDbContext.BulkUpdateAsync(zap, x => x.PropertiesToInclude = new List <string> { nameof(TemporaryExposureKeyEntity.PublishingState) }); count += used.Length; used = _PublishingDbContext.Set <EksCreateJobInputEntity>() .Where(x => x.Used) .Skip(count) .Select(x => x.Id) .Take(100) .ToArray(); } _WorkflowDbContext.SaveAndCommit(); } _Logger.LogInformation($"Cleanup job tables."); await _PublishingDbContext.Set <EksCreateJobInputEntity>().BatchDeleteAsync(); await _PublishingDbContext.Set <EksCreateJobOutputEntity>().BatchDeleteAsync(); _PublishingDbContext.SaveAndCommit(); } }
private async Task InnerExecute(byte[] signature, byte[] body) { _Logger.LogDebug("Signature received: {Signature}", signature); _BodyBytes = body; if ((signature?.Length ?? 0) != _WorkflowConfig.PostKeysSignatureLength) { _Logger.LogError("Signature is null or incorrect length."); return; } try { var argsJson = Encoding.UTF8.GetString(_BodyBytes); _Logger.LogDebug("Body -\n{ArgsJson}.", argsJson); _ArgsObject = _JsonSerializer.Deserialize <PostTeksArgs>(argsJson); } catch (Exception e) { _Logger.LogError("Error reading body -\n{E}", e.ToString()); return; } var base64Parser = new Base64(); var base64ParserResult = base64Parser.TryParseAndValidate(_ArgsObject.BucketId, _WorkflowConfig.BucketIdLength); if (!base64ParserResult.Valid) { _Logger.LogValidationMessages(base64ParserResult.Messages.Select(x => $"BuckedId - {x}").ToArray()); return; } _BucketIdBytes = base64ParserResult.Item; if (_Logger.LogValidationMessages(_KeyValidator.Validate(_ArgsObject))) { return; } var teks = _ArgsObject.Keys.Select(Mapper.MapToTek).ToArray(); foreach (var i in teks) { i.PublishAfter = _DateTimeProvider.Snapshot; } if (_Logger.LogValidationMessages(new TekListDuplicateValidator().Validate(teks))) { return; } //Validation ends, filtering starts var filterResult = _TekApplicableWindowFilter.Execute(teks); teks = filterResult.Items; _Logger.LogFilterMessages(filterResult.Messages); _Logger.LogInformation("TEKs remaining - Count:{count}.", teks.Length); var workflow = _DbContext .KeyReleaseWorkflowStates .Include(x => x.Teks) .SingleOrDefault(x => x.BucketId == _BucketIdBytes); if (workflow == null) { _Logger.LogError("Workflow does not exist - {BucketId}.", _ArgsObject.BucketId); return; } if (!_SignatureValidator.Valid(signature, workflow.ConfirmationKey, _BodyBytes)) { _Logger.LogError("Signature not valid: {Signature}", signature); return; } var filterResults = _TekListWorkflowFilter.Filter(teks, workflow); _Logger.LogFilterMessages(filterResults.Messages); _Logger.LogInformation("TEKs remaining - Count:{count}.", teks.Length); //Run after the filter removes the existing TEKs from the args. var allTeks = workflow.Teks.Select(Mapper.MapToTek).Concat(filterResults.Items).ToArray(); if (_Logger.LogValidationMessages(new TekListDuplicateKeyDataValidator().Validate(allTeks))) { return; } _Logger.LogDebug("Writing."); var writeArgs = new TekWriteArgs { WorkflowStateEntityEntity = workflow, NewItems = filterResults.Items }; await _Writer.Execute(writeArgs); _DbContext.SaveAndCommit(); _Logger.LogDebug("Committed."); if (filterResults.Items.Length != 0) { _Logger.LogInformation("Teks added - Count:{FilterResultsLength}.", filterResults.Items.Length); } }
public async Task CommitResults() { await using (_ContentDbContext.BeginTransaction()) { var move = _ContentDbContext.EksOutput.Select( x => new ExposureKeySetContentEntity { Release = x.Release, Content = x.Content, ContentTypeName = MediaTypeNames.Application.Zip, CreatingJobName = x.CreatingJobName, CreatingJobQualifier = x.CreatingJobQualifier, PublishingId = _PublishingId.Create(x.Content) }).ToArray(); //TODO copy? Cos it's the same DB cos 'policy' _ContentDbContext.ExposureKeySetContent.AddRange(move); _ContentDbContext.SaveAndCommit(); } await using (_ContentDbContext.BeginTransaction()) //Read-only await using (_WorkflowDbContext.BeginTransaction()) { var count = 0; var used = _ContentDbContext.Set <EksCreateJobInputEntity>() .Where(x => x.Used) .Skip(count) .Select(x => x.Id) .Take(100) .ToArray(); while (used.Length > 0) { var zap = _WorkflowDbContext.TemporaryExposureKeys .Where(x => used.Contains(x.Id)) .ToList(); foreach (var i in zap) { i.PublishingState = PublishingState.Published; } await _WorkflowDbContext.BulkUpdateAsync(zap, x => x.PropertiesToInclude = new List <string>() { nameof(TemporaryExposureKeyEntity.PublishingState) }); count += used.Length; used = _ContentDbContext.Set <EksCreateJobInputEntity>() .Where(x => x.Used) .Skip(count) .Select(x => x.Id) .Take(100) .ToArray(); } _WorkflowDbContext.SaveAndCommit(); } await _ContentDbContext.EksInput.BatchDeleteAsync(); await _ContentDbContext.EksOutput.BatchDeleteAsync(); _ContentDbContext.SaveAndCommit(); }