public async Task Execute( HttpContext context, IServiceInstance service, CancellationToken cancellationToken ) { DateTimeOffset start = ServiceClock.CurrentTime(); ServiceResponse output; Guid? correlationId = null; try { var input = await _converter.ConvertRequest(service.RequestType, context.Request, new HttpDataSerializerOptions()); correlationId = input.CorrelationId; output = await service.Execute(input, cancellationToken); } catch (ValidationErrorException vex) { output = new ServiceResponse( new ResponseMetaData( service, ServiceResult.ValidationError, validationErrors: ValidationHelper.Create(vex.Error, vex.Member))); } await _converter.ConvertResponse(output, service.ResponseType, context.Response); }
protected BaseTable() { Version = 1; SchemaVersion = 1; Created = ServiceClock.CurrentTime(); Modified = ServiceClock.CurrentTime(); }
protected override void RegisterTriggerActions(RegistrationFactory register) { register.OnTrigger(Trigger.UpdateTime) .Do((request, token) => { CurrentData.Now = ServiceClock.CurrentTime(); return(Task.CompletedTask); }); }
public async Task GenerateToken() { ServiceClock.CurrentTime = () => new DateTimeOffset(2020,01,01,1,0,0, TimeSpan.Zero); // ARRANGE var jwt = new JwtServices(new UserResolverSecretBasic("ABC"), NullLoggerFactory.Instance.CreateLogger<JwtServices>()); var token = await jwt.Generate(new UserInformation { Username = "******", UserIdentifier = "12345", Roles = new[] { "A" } }, Guid.Empty, null, CancellationToken.None); Assert.AreEqual("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJUZXN0IiwidWlkIjoiMTIzNDUiLCJpYXQiOjE1Nzc4NDA0MDAsInJvbGVzIjpbIkEiXX0.-cgfiJfrxO3u_7gfq1ErHLrDpQG8vwXGVw8BrBIxTZuNxdptzl08mxAsLlLql9Y7FLinSasYXKvQLvn7mrQWMw", token); ServiceClock.ResetToUtc(); }
protected override async Task <ServiceResponse <TimeResponse> > Implementation(TimeRequest request, CancellationToken cancellationToken) { var time = ServiceClock.CurrentTime(); var localTime = DateTimeOffset.Now; if (request.AddDelayMs > 0) { await Task.Delay(request.AddDelayMs, cancellationToken); } var response = new TimeResponse { CurrentTime = request.Zone == TimeZone.Local ? localTime : time, Zone = request.Zone }; return(Successful(response)); }
protected BaseStatefulServiceInstance( CoreDependencies coreDependencies, StatefulDependencies statefulDependencies) : base(coreDependencies) { _stateRepository = statefulDependencies.StateRepository; _currentEnvironment = coreDependencies.EnvironmentResolver.Environment; CreatedDate = ServiceClock.CurrentTime(); ModifiedDate = CreatedDate; // REMOVE THE DEFAULT VALIDATION AND REPLACE WITH THE STATEFUL VALIDATION SERVICE var existingValidation = PipeLine.FirstOrDefault(x => typeof(ValidationMiddleware) == x.GetType()); var idx = PipeLine.IndexOf(existingValidation); PipeLine.RemoveAt(idx); PipeLine.Insert(idx, new StateMachineValidatorMiddleware <TTrigger>(coreDependencies.RequestValidator)); _data = new TData(); Machine = new StateMachine <TState, TTrigger>(() => _data.State, s => _data.State = s); Machine.OnTransitionCompletedAsync(OnTransitionAction); }
public Task <string> Generate(UserInformation user, Guid correlationId, TimeSpan?expiresIn, CancellationToken cancellationToken) { var token = new JwtBuilder() .WithAlgorithm(new HMACSHA512Algorithm()) .WithSecret(_userResolverSecret.GetSecret()) .AddClaim("sub", user.Username) .AddClaim("uid", user.UserIdentifier) .AddClaim("iat", ServiceClock.CurrentTime().ToUnixTimeSeconds()) ; if (expiresIn != null) { token.AddClaim("exp", ServiceClock.CurrentTime().Add(expiresIn.Value).ToUnixTimeSeconds()); } if (user.Roles != null && user.Roles.Length > 0) { token.AddClaim("roles", user.Roles); } else { token.AddClaim("roles", new string[0]); } if (user.Claims != null && user.Claims.Any()) { foreach (var claim in user.Claims) { string[] ignore = { "exp", "roles", "uid", "iat", "sub" }; if (!ignore.Contains(claim.Key)) { token.AddClaim(claim.Key, claim.Value); } } } var tokenStr = token.Encode(); _logger.LogTrace($"Generated, token: {tokenStr}, correlationId: {correlationId}"); return(Task.FromResult(tokenStr)); }
protected override void RegisterTriggerActions(RegistrationFactory register) { register.OnTrigger(Trigger.Open) .WhenInState(State.Pending) .Do((req, ct) => { var data = As <AccountRequest.OpenData>(req); CurrentData.Name = data.Name; CurrentData.OpenDate = ServiceClock.CurrentTime(); CurrentData.Ssn = data.Ssn; CurrentData.InitialBalance = req.Open.InitialBalance.GetValueOrDefault(0); return(Task.CompletedTask); }); register.OnTrigger(Trigger.Update) .Do(async(req, ct) => { await Task.CompletedTask; var data = As <AccountRequest.UpdateData>(req); CurrentData.Name = data.Name; SetErrorCode(100, ErrorAction.AllowTrigger); }); }
protected ThirdPartyCall(IStateRepository stateRepository) { _stateRepository = stateRepository; var allowManual = AllowManualOverride(); _machine.OnTransitionCompletedAsync(async x => { var nextSequenceNumber = await _stateRepository.StoreStateData <ThirdPartyStateData, State>(new StateDto { Trigger = x.Trigger.ToString(), Destination = x.Destination.ToString(), MachineName = MachineName, IsReentry = x.IsReentry, Source = x.Source.ToString(), Created = _created, Modified = _modified, SequenceNumber = _sequenceNumber, Identifier = _statefulIdentifier.Identifier, CorrelationId = _correlationId }, _sequenceNumber, Data, saveHistory: true, _statefulIdentifier.ParentIdentifier); _sequenceNumber = nextSequenceNumber; _modified = ServiceClock.CurrentTime(); }); _machine.Configure(State.BeforeRequest) .SubstateOf(State.InProcess); _machine.Configure(State.Pending) .SubstateOf(State.BeforeRequest) .Permit(Trigger.Verify, State.Verification); _machine.Configure(State.Verification) .SubstateOf(State.BeforeRequest) .OnEntryAsync(InternalVerify) .Permit(Trigger.ExecuteRequest, State.Requested) .Permit(Trigger.SuccessfulResponse, State.Completed) .Permit(Trigger.NoResponse, State.Unknown); _machine.Configure(State.Requested) .SubstateOf(State.BeforeRequest) .OnEntryAsync(InternalRequest) .Permit(Trigger.SuccessfulResponse, State.Completed) .Permit(Trigger.ErrorResponse, State.Error) .Permit(Trigger.NoResponse, State.Unknown); _machine.Configure(State.Error) .SubstateOf(State.AfterRequest) .Permit(Trigger.Reset, State.Pending); _machine.Configure(State.Unknown) .SubstateOf(State.AfterRequest) .Permit(Trigger.Reset, State.Pending); _machine.Configure(State.Completed) .SubstateOf(State.Terminal); _machine.Configure(State.Failed) .SubstateOf(State.Terminal); _machine.Configure(State.Pending).Permit(Trigger.ToFailed, State.Failed); _machine.Configure(State.Verification).Permit(Trigger.ToFailed, State.Failed); _machine.Configure(State.Error).Permit(Trigger.ToFailed, State.Failed); _machine.Configure(State.Unknown).Permit(Trigger.ToFailed, State.Failed); _machine.Configure(State.Completed).Permit(Trigger.ToFailed, State.Failed); if (allowManual) { _machine.Configure(State.Manual) .SubstateOf(State.AfterRequest) .Permit(Trigger.SuccessfulResponse, State.Completed) .Permit(Trigger.ErrorResponse, State.Failed); _machine.Configure(State.Pending).Permit(Trigger.ToManual, State.Manual); _machine.Configure(State.Verification).Permit(Trigger.ToManual, State.Manual); _machine.Configure(State.Error).Permit(Trigger.ToManual, State.Manual); _machine.Configure(State.Unknown).Permit(Trigger.ToManual, State.Manual); _machine.Configure(State.Completed).Permit(Trigger.ToManual, State.Manual); _machine.Configure(State.Failed).Permit(Trigger.ToManual, State.Manual); } }
public async Task <HttpResponseMessage> Handle( HttpRequestMessage request, IServiceInstance service, CancellationToken cancellationToken) { var start = ServiceClock.CurrentTime(); try { var input = await _responseGenerator.ConvertRequest(service.RequestType, request); var output = await service.Execute(input, cancellationToken); var response = await _responseGenerator.ConvertResponse(request, output, service.ResponseType); return(response); } catch (SchemaValidationException ex) { var error = await _responseGenerator.ConvertResponse( request, new ServiceResponse( new ResponseMetaData( service.FullName, service.CorrelationId == default(Guid) ? Guid.Empty : service.CorrelationId, ServiceResult.ValidationError, (long)(ServiceClock.CurrentTime() - start).TotalMilliseconds, ServiceClock.CurrentTime(), validationErrors: ex.Errors ) ), service.ResponseType); return(error); } catch (Exception ex) { var serialEx = ex as CodeWorksSerializationException; string originalPayload = serialEx?.RawData ?? ""; Dictionary <string, string[]> errors = null; if (!string.IsNullOrWhiteSpace(originalPayload)) { errors = new Dictionary <string, string[]> { ["payload"] = new[] { originalPayload } }; } var error = await _responseGenerator.ConvertResponse( request, new ServiceResponse( new ResponseMetaData( service.FullName, service.CorrelationId == default(Guid) ? Guid.Empty : service.CorrelationId, ServiceResult.PermanentError, (long)(ServiceClock.CurrentTime() - start).TotalMilliseconds, ServiceClock.CurrentTime(), validationErrors: errors, exceptionMessage: ex.ToString() ) ), service.ResponseType); return(error); } }
public async Task <ServiceResponse <TResponse> > Call <TRequest, TResponse>(TRequest request, IDictionary <string, object> data, CancellationToken cancellationToken) where TRequest : BaseRequest where TResponse : new() { if (data == null) { throw new ArgumentNullException(nameof(data)); } Uri uri = null; if (data.TryGetValue("uri", out object uriObj)) { uri = uriObj as Uri; } if (uri == null) { throw new Exception("Expected a data entry called \"uri\" of the type Uri with a reference to the Http Service URL"); } _logger.LogTrace("Calling Uri:{uri}, Request:{request?.CorrelationId}", uri, request?.CorrelationId); var options = _optionsResolver?.Options() ?? new HttpDataSerializerOptions(); DateTimeOffset start = ServiceClock.CurrentTime(); _logger.LogTrace("Serializing request payload {request}, Request:{request?.CorrelationId}", request, request?.CorrelationId); var payload = await _dataSerializer.SerializeRequest(request, typeof(TRequest), options); _logger.LogTrace("Serialized request payload {payload}, Request:{request?.CorrelationId}", payload, request?.CorrelationId); var requestMsg = new HttpRequestMessage(HttpMethod.Post, uri); if (options.EnumSerializationMethod != default) { _logger.LogTrace("Options.EnumSerializationMethod:{method} RequestId:{request}", options.EnumSerializationMethod, request?.CorrelationId); requestMsg.Headers.Add("codeworks-prefs-enum", options.EnumSerializationMethod.ToString()); } if (options.JsonSchemaValidation != default) { _logger.LogTrace("Options.JsonSchemaValidation:{method} RequestId:{request}", options.JsonSchemaValidation, request?.CorrelationId); requestMsg.Headers.Add("codeworks-prefs-schema-check", options.JsonSchemaValidation.ToString()); } if (options.IncludeDependencyMetaData != default) { _logger.LogTrace("options.IncludeDependencyMetaData:{includeDependencyMetaData} RequestId:{{request}}", options.IncludeDependencyMetaData, request?.CorrelationId); requestMsg.Headers.Add("codeworks-prefs-dep-meta", options.IncludeDependencyMetaData.ToString()); } requestMsg.Content = new StringContent(payload, Encoding.UTF8, "application/json"); var apiResponse = await _client.SendAsync(requestMsg, cancellationToken); var responseData = await apiResponse.Content.ReadAsByteArrayAsync(); if (_logger.IsEnabled(LogLevel.Trace)) { var contents = Encoding.UTF8.GetString(responseData); _logger.LogTrace("Serialized response payload {contents}, Request:{request?.CorrelationId}", contents, request?.CorrelationId); } InternalServiceResponse <TResponse> response = null; try { response = await _dataSerializer .DeserializeResponse <InternalServiceResponse <TResponse> >(responseData); } catch (CodeWorksSerializationException ex) { return(new ServiceResponse <TResponse> (default(TResponse), new ResponseMetaData( uri.ToString(), request?.CorrelationId ?? Guid.Empty, ServiceResult.PermanentError, (long)(ServiceClock.CurrentTime() - start).TotalMilliseconds, exceptionMessage: ex.ToString() ))); } Dictionary <string, ResponseMetaData> dependencies = null; if (options.IncludeDependencyMetaData == IncludeDependencyMetaDataStrategy.Full) { //TODO: Currently handles 1 level of dependencies - need to add recursion dependencies = new Dictionary <string, ResponseMetaData> { { response.MetaData.ServiceName, new ResponseMetaData( response.MetaData.ServiceName, response.MetaData.CorrelationId, response.MetaData.Result, response.MetaData.DurationMs, response.MetaData.ResponseCreated, response.MetaData.ErrorCodes?.ToDictionary(k => Convert.ToInt32(k.Key), v => v.Value), response.MetaData.ValidationErrors, response.MetaData.PublicMessage, response.MetaData.ExceptionMessage, response.MetaData.Dependencies ) } }; } var end = ServiceClock.CurrentTime(); return(new ServiceResponse <TResponse>( response.Data, new ResponseMetaData( $"{response.MetaData.ServiceName}.Client", response.MetaData.CorrelationId, response.MetaData.Result, (long)(end - start).TotalMilliseconds, end, response.MetaData.ErrorCodes?.ToDictionary(k => Convert.ToInt32(k.Key), v => v.Value), response.MetaData.ValidationErrors, response.MetaData.PublicMessage, response.MetaData.ExceptionMessage, dependencies))); //TODO: FIX ERROR DATA }