Пример #1
0
        public async Task <NegotiationResponse> NegotiateAsync(string hubName, HttpContext httpContext = null, string userId = null, IEnumerable <Claim> claims = null, TimeSpan?lifetime = null, bool isDiagnosticClient = false, CancellationToken cancellationToken = default)
        {
            try
            {
                if (cancellationToken == default && httpContext != null)
                {
                    cancellationToken = httpContext.RequestAborted;
                }

                var candidateEndpoints = _serviceEndpointManager.GetEndpoints(hubName);
                var selectedEndpoint   = _router.GetNegotiateEndpoint(httpContext, candidateEndpoints);
                var provider           = _serviceEndpointManager.GetEndpointProvider(selectedEndpoint);

                Func <IEnumerable <Claim> > claimProvider = null;
                if (claims != null)
                {
                    claimProvider = () => claims;
                }
                var claimsWithUserId = ClaimsUtility.BuildJwtClaims(httpContext?.User, userId: userId, claimProvider, isDiagnosticClient: isDiagnosticClient);

                var tokenTask = provider.GenerateClientAccessTokenAsync(hubName, claimsWithUserId, lifetime);
                await tokenTask.OrTimeout(cancellationToken, Timeout, GeneratingTokenTaskDescription);

                return(new NegotiationResponse
                {
                    Url = provider.GetClientEndpoint(hubName, null, null),
                    AccessToken = tokenTask.Result
                });
            }
            catch (Exception e)
            {
                throw new AzureSignalRException(ErrorMsg, e);
            }
        }
Пример #2
0
        public async Task Call_NegotiateAsync_After_WithEndpoints(ServiceTransportType serviceTransportType)
        {
            var serviceManager = new ServiceManagerBuilder()
                                 .WithOptions(o =>
            {
                o.ServiceTransportType = serviceTransportType;
                o.ServiceEndpoints     = ServiceEndpoints;
            })
                                 .BuildServiceManager();
            var hubContext = await serviceManager.CreateHubContextAsync(Hub, default);

            for (var i = 0; i < 5; i++)
            {
                var randomEndpoint      = ServiceEndpoints[StaticRandom.Next(0, Count)];
                var negotiationResponse = await(hubContext as IInternalServiceHubContext)
                                          .WithEndpoints(new ServiceEndpoint[] { randomEndpoint })
                                          .NegotiateAsync();

                Assert.Equal(ClientEndpointUtils.GetExpectedClientEndpoint(Hub, null, randomEndpoint.Endpoint), negotiationResponse.Url);
                var tokenString   = negotiationResponse.AccessToken;
                var token         = JwtTokenHelper.JwtHandler.ReadJwtToken(tokenString);
                var expectedToken = JwtTokenHelper.GenerateJwtBearer(
                    ClientEndpointUtils.GetExpectedClientEndpoint(Hub, null, randomEndpoint.Endpoint),
                    ClaimsUtility.BuildJwtClaims(null, null, null), token.ValidTo, token.ValidFrom, token.ValidFrom, randomEndpoint.AccessKey);
                Assert.Equal(expectedToken, tokenString);
            }
        }
Пример #3
0
        public async Task <IActionResult> Create(CreateWorkflowCommand command)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            if (command.Inputs == null)
            {
                //Set to an empty dictionary if null
                command.Inputs = new Dictionary <string, object>();
            }
            try
            {
                command.CreatedBy = ClaimsUtility.GetId(User);
                var result = await Mediator.Send(command);

                return(Ok(new HttpCommandResult <Workflow>("workflow", result, result.Result)));
            }
            catch (BaseException e)
            {
                Logger.LogError(e.Message);
                stopwatch.Stop();
                return(BadRequest(e.ToExceptionResult(stopwatch.ElapsedMilliseconds)));
            }
        }
Пример #4
0
        public async Task <IActionResult> Create([FromBody] CreateExecutionTemplateVM command)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            try
            {
                var result = await Mediator.Send(new CreateExecutionTemplateCommand()
                {
                    CreatedBy             = ClaimsUtility.GetId(User),
                    Description           = command.Description,
                    ExecutionTemplateType = command.ExecutionTemplateType.ToLower(),
                    Inputs      = command.Inputs,
                    Name        = command.Name,
                    ReferenceId = command.ReferenceId
                });


                return(Ok(new HttpCommandResult <ExecutionTemplate>("/api/execution-template/" + command.Name, result, null)));
            }
            catch (BaseException e)
            {
                Logger.LogError(e.Message);
                stopwatch.Stop();
                return(BadRequest(e.ToExceptionResult(stopwatch.ElapsedMilliseconds)));
            }
        }
Пример #5
0
        public async Task <IActionResult> Create([FromBody] CreateWorkflowTemplateCommand command)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            if (command.InputDefinitions == null)
            {
                command.InputDefinitions = new Dictionary <string, Domain.ValueObjects.DynamicDataDescription>();
            }

            if (command.LogicBlocks == null)
            {
                command.InputDefinitions = new Dictionary <string, Domain.ValueObjects.DynamicDataDescription>();
            }
            try
            {
                command.CreatedBy = ClaimsUtility.GetId(User);
                var result = await Mediator.Send(command);

                return(Ok(new HttpCommandResult <WorkflowTemplate>("/api/workflowTemplate/" + command.Name + "/" + command.Version, result, null)));
            }
            catch (BaseException e)
            {
                Logger.LogError(e.Message);
                stopwatch.Stop();
                return(BadRequest(e.ToExceptionResult(stopwatch.ElapsedMilliseconds)));
            }
        }
Пример #6
0
        public async Task <IActionResult> Create([FromBody] CreateStepTemplateCommand command)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            if (command.ReferenceId == null && (command.Name == null || command.Version == null))
            {
                return(BadRequest("Either referenceId needs to be set or name and version must be set."));
            }

            try
            {
                if (command.OutputDefinitions == null)
                {
                    command.OutputDefinitions = new Dictionary <string, Domain.ValueObjects.DynamicDataDescription>();
                }

                command.CreatedBy = ClaimsUtility.GetId(User);
                var result = await Mediator.Send(command);

                return(Ok(new HttpCommandResult <StepTemplate>("/api/steptemplates/" + command.Name + "/" + command.Version, result, null)));
            }
            catch (BaseException e)
            {
                Logger.LogError(e.Message);
                stopwatch.Stop();
                return(BadRequest(e.ToExceptionResult(stopwatch.ElapsedMilliseconds)));
            }
        }
Пример #7
0
        public async Task <IActionResult> Create([FromBody] CreateExecutionScheduleVM command, bool?runImmediately = false)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            try
            {
                var result = await Mediator.Send(new CreateExecutionScheduleCommand()
                {
                    CreatedBy             = ClaimsUtility.GetId(User),
                    Description           = command.Description,
                    Name                  = command.Name,
                    RunImmediately        = runImmediately.HasValue ? runImmediately.Value : false,
                    ExecutionTemplateName = command.ExecutionTemplateName,
                    Schedule              = command.Schedule
                });


                return(Ok(new HttpCommandResult <ExecutionSchedule>("/api/execution-schedules/" + command.Name, result, null)));
            }
            catch (BaseException e)
            {
                Logger.LogError(e.Message);
                stopwatch.Stop();
                return(BadRequest(e.ToExceptionResult(stopwatch.ElapsedMilliseconds)));
            }
        }
Пример #8
0
 public async Task <IActionResult> ScanWorkflow(Guid id)
 {
     return(Ok(await Mediator.Send(new ScanWorkflowCommand()
     {
         CreatedBy = ClaimsUtility.GetId(User),
         WorkflowId = id
     })));
 }
Пример #9
0
 public async Task <IActionResult> Execute(string name)
 {
     return(Ok(await Mediator.Send(new ExecuteExecutionTemplateCommand()
     {
         Name = name,
         CreatedBy = ClaimsUtility.GetId(User)
     })));
 }
        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            var user = await UserService.GetAsync(context.UserName, context.Password);

            if (user != null)
            {
                var claims = ClaimsUtility.GetClaims(user);
                context.Result = new GrantValidationResult(user.Id.ToString(), "password", claims);
            }
        }
Пример #11
0
        public async Task <IActionResult> Get()
        {
            var username = ClaimsUtility.GetUsername(User);
            var user     = (await Mediator.Send(new GetEntityQuery <User>()
            {
                Expression = u => u.Username == username
            }));

            return(Ok(new HttpQueryResult <User, UserVM>(user, Mapper.Map <UserVM>(user.Result))));
        }
Пример #12
0
        public async Task <IActionResult> UpdateStepStatus(Guid id, PutStepStatus putModel)
        {
            IRequest <CommandResult> request;

            switch (putModel.Status)
            {
            case StepStatuses.Suspended:
                request = new SuspendStepCommand()
                {
                    StepId         = id,
                    CreatedBy      = ClaimsUtility.GetId(User),
                    SuspendedUntil = putModel.SuspendedUntil
                };
                break;

            case StepStatuses.Cancelled:
                request = new CancelStepCommand()
                {
                    StepId    = id,
                    CreatedBy = ClaimsUtility.GetId(User)
                };
                break;

            case StepStatuses.Unassigned:
                request = new UnassignStepCommand()
                {
                    StepId    = id,
                    CreatedBy = ClaimsUtility.GetId(User)
                };
                break;

            default:
                return(BadRequest(new ExceptionResult()
                {
                    ExceptionName = "InvalidStepStatusException",
                    Message = "Step status given was not valid. Steps can only be suspended, unassigned or cancelled by users"
                }));
            }

            var result = await Mediator.Send(request);

            if (result.ObjectRefId != "")
            {
                var resolvedStep = (await Mediator.Send(new GetEntityQuery <Step>()
                {
                    Expression = s => s.Id == new Guid(result.ObjectRefId)
                })).Result;
                return(Ok(new HttpCommandResult <Step>("step", result, resolvedStep)));
            }
            else
            {
                return(Ok(new HttpCommandResult <Step>("", result, null)));
            }
        }
Пример #13
0
        public async Task <ActionResult> RolesCheck(FormCollection form)
        {
            var UserName = (String)form["UserName"];
            var pools    = await this.Svc.GetPoolsAsync();

            var ClaimsUtil = new ClaimsUtility(Auth, await this.Svc.GetPoolsAsync(), Properties.Settings.Default.AdministratorADGroup);
            var identity   = ClaimsUtil.BuildClaimsIdentityForUser(UserName);

            ViewBag.User = new ClaimsPrincipal(identity);
            return(View("Roles", pools));
        }
Пример #14
0
        public async Task <IActionResult> Put(string name, [FromBody] UpdateGlobalValueVM globalValue)
        {
            var result = await Mediator.Send(new UpdateGlobalValueCommand()
            {
                Description = globalValue.Description,
                Name        = name,
                Value       = globalValue.Value,
                CreatedBy   = ClaimsUtility.GetId(User)
            });

            return(Ok(new HttpCommandResult <GlobalValue>("//api//global-values//" + result.ObjectRefId, result, result.Result)));
        }
Пример #15
0
        public async Task <IActionResult> Post([FromBody] CreateGlobalValueVM globalValue)
        {
            var result = await Mediator.Send(new CreateGlobalValueCommand()
            {
                Description = globalValue.Description,
                Name        = globalValue.Name,
                Type        = globalValue.Type.ToLower(),
                Value       = globalValue.Value,
                CreatedBy   = ClaimsUtility.GetId(User)
            });

            return(Ok(new HttpCommandResult <GlobalValue, GlobalValueVM>("//api//global-values//" + result.ObjectRefId, result, Mapper.Map <GlobalValueVM>(result.Result))));
        }
        private IEnumerable <Claim> BuildClaims(IOwinContext owinContext, IRequest request)
        {
            // Pass appname through jwt token to client, so that when client establishes connection with service, it will also create a corresponding AppName-connection
            yield return(new Claim(Constants.ClaimType.AppName, _appName));

            var user   = owinContext.Authentication?.User;
            var userId = _provider?.GetUserId(request);

            var claims = ClaimsUtility.BuildJwtClaims(user, userId, GetClaimsProvider(owinContext));

            foreach (var claim in claims)
            {
                yield return(claim);
            }
        }
Пример #17
0
        private IEnumerable <Claim> BuildClaims(HostContext context)
        {
            // Pass appname through jwt token to client, so that when client establishes connection with service, it will also create a corresponding AppName-connection
            yield return(new Claim(Constants.ClaimType.AppName, _appName));

            var user   = new Owin.OwinContext(context.Environment).Authentication?.User;
            var userId = UserIdProvider?.GetUserId(context.Request);

            var claims = ClaimsUtility.BuildJwtClaims(user, userId, null);

            foreach (var claim in claims)
            {
                yield return(claim);
            }
        }
Пример #18
0
        private IEnumerable <Claim> BuildClaims(IOwinContext owinContext, IRequest request)
        {
            // Pass appname through jwt token to client, so that when client establishes connection with service, it will also create a corresponding AppName-connection
            yield return(new Claim(Constants.ClaimType.AppName, _appName));

            var user   = owinContext.Authentication?.User;
            var userId = _provider?.GetUserId(request);
            var claims = ClaimsUtility.BuildJwtClaims(user, userId, GetClaimsProvider(owinContext), _serverName, _mode, _enableDetailedErrors, _endpointsCount, _maxPollInterval, IsDiagnosticClient(owinContext));

            yield return(new Claim(Constants.ClaimType.Version, AssemblyVersion));

            foreach (var claim in claims)
            {
                yield return(claim);
            }
        }
Пример #19
0
        public async Task <NegotiationResponse> NegotiateAsync(string hubName, NegotiationOptions negotiationOptions, CancellationToken cancellationToken = default)
        {
            negotiationOptions ??= NegotiationOptions.Default;
            var httpContext          = negotiationOptions.HttpContext;
            var userId               = negotiationOptions.UserId;
            var claims               = negotiationOptions.Claims;
            var isDiagnosticClient   = negotiationOptions.IsDiagnosticClient;
            var enableDetailedErrors = negotiationOptions.EnableDetailedErrors;
            var lifetime             = negotiationOptions.TokenLifetime;

            try
            {
                if (cancellationToken == default && httpContext != null)
                {
                    cancellationToken = httpContext.RequestAborted;
                }

                var candidateEndpoints = _serviceEndpointManager.GetEndpoints(hubName);
                var selectedEndpoint   = _router.GetNegotiateEndpoint(httpContext, candidateEndpoints);
                var provider           = _serviceEndpointManager.GetEndpointProvider(selectedEndpoint);

                Func <IEnumerable <Claim> > claimProvider = null;
                if (claims != null)
                {
                    claimProvider = () => claims;
                }
                var claimsWithUserId = ClaimsUtility.BuildJwtClaims(httpContext?.User, userId: userId, claimProvider, enableDetailedErrors: enableDetailedErrors, isDiagnosticClient: isDiagnosticClient);

                var tokenTask = provider.GenerateClientAccessTokenAsync(hubName, claimsWithUserId, lifetime);
                await tokenTask.OrTimeout(cancellationToken, Timeout, GeneratingTokenTaskDescription);

                return(new NegotiationResponse
                {
                    Url = provider.GetClientEndpoint(hubName, null, null),
                    AccessToken = tokenTask.Result
                });
            }
            catch (Exception e) when(e is OperationCanceledException || e is TimeoutException)
            {
                throw new AzureSignalRException(ErrorMsg, e);
            }
        }
Пример #20
0
        public async Task <IActionResult> UnencryptStepSecret(Guid id, string fieldName, string type)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            try
            {
                return(Ok(await Mediator.Send(new UnencryptStepFieldQuery()
                {
                    StepId = id,
                    FieldName = fieldName,
                    UserId = ClaimsUtility.GetId(User),
                    Type = type.ToLower()
                })));
            }
            catch (BaseException e)
            {
                Logger.LogError(e.Message);
                return(BadRequest(e.ToExceptionResult(stopwatch.ElapsedMilliseconds)));
            }
        }
Пример #21
0
        public async Task <IActionResult> GetNextStep(AssignStepCommand command)
        {
            try
            {
                command.BotId = new Guid(ClaimsUtility.GetId(User));
                var result = await Mediator.Send(command);

                if (result.ObjectRefId != "")
                {
                    return(Ok(new HttpCommandResult <Step>("step", result, result.Result)));
                }
                else
                {
                    return(Ok(new HttpCommandResult <Step>("", result, null)));
                }
            }
            catch (BotKeyAssignmentException e)
            {
                return(BadRequest(command.BotId + " has been disabled for assignment."));
            }
        }
Пример #22
0
        public async Task <IActionResult> Create(CreateStepCommand command, bool?wait_for_completion, string timeout = "30s")
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            try
            {
                command.CreatedBy = ClaimsUtility.GetId(User);
                var result = await Mediator.Send(command);

                Step step = (await Mediator.Send(new GetEntityQuery <Step>()
                {
                    Expression = s => s.Id == new Guid(result.ObjectRefId),
                    Exclude = (s) => s.Journal
                })).Result;


                if (wait_for_completion.HasValue && wait_for_completion.Value)
                {
                    var ms = DateTimeMathsUtility.GetMs(timeout);

                    while (!StepStatuses.IsCompleteStatus(step.Status) && stopwatch.ElapsedMilliseconds < ms)
                    {
                        step = (await Mediator.Send(new GetEntityQuery <Step>()
                        {
                            Expression = s => s.Id == new Guid(result.ObjectRefId)
                        })).Result;
                    }
                }


                return(Ok(new HttpCommandResult <Step>("step", result, step)));
            }
            catch (BaseException e)
            {
                Logger.LogError(e.Message);
                stopwatch.Stop();
                return(BadRequest(e.ToExceptionResult(stopwatch.ElapsedMilliseconds)));
            }
        }
Пример #23
0
        public async Task <ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (Auth.Authenticate(model.UserName, model.Password))
                {
                    // Build the set of claims for the authenticated user for the various Pools & application administrator
                    var ClaimsUtil = new ClaimsUtility(Auth, await this.Svc.GetPoolsAsync(), Properties.Settings.Default.AdministratorADGroup);
                    var identity   = ClaimsUtil.BuildClaimsIdentityForUser(model.UserName);
                    await SignInAsync(identity, false);

                    return(RedirectToLocal(returnUrl));
                }
                else
                {
                    ModelState.AddModelError("", Properties.Resources.InvalidUserNameOrPassword);
                }
            }

            // If we got this far, something failed, redisplay form
            return(View(model));
        }
Пример #24
0
        public async Task <IActionResult> AddLog(Guid id, AppendStepLogVM command)
        {
            var appendCommand = new AppendStepLogCommand()
            {
                StepId    = id,
                Log       = command.Log,
                CreatedBy = ClaimsUtility.GetId(User)
            };
            var result = await Mediator.Send(appendCommand);

            if (result.ObjectRefId != "")
            {
                var resolvedStep = (await Mediator.Send(new GetEntityQuery <Step>()
                {
                    Expression = s => s.Id == new Guid(result.ObjectRefId)
                })).Result;
                return(Ok(new HttpCommandResult <Step>("step", result, resolvedStep)));
            }
            else
            {
                return(Ok(new HttpCommandResult <Step>("", result, null)));
            }
        }
Пример #25
0
        public async Task <IActionResult> Register(CreateBotKeyCommand command)
        {
            if (!_clusterState.GetSettings.AllowAutoRegistration)
            {
                if (ClaimsUtility.GetId(User) == null)
                {
                    return(Unauthorized());
                }
            }

            var keyCreationResult = await Mediator.Send(command);

            var key = await Mediator.Send(new GetEntityQuery <BotKey>()
            {
                Expression = bk => bk.Id == new Guid(keyCreationResult.ObjectRefId)
            });

            return(Ok(new HttpCommandResult <NewBotKeyVM>("", keyCreationResult, new NewBotKeyVM()
            {
                // BotName = key.Result.BotName,
                IdKey = keyCreationResult.ObjectRefId
            })));
        }
Пример #26
0
        public async Task <IActionResult> Post(CreateUserVM request)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            try
            {
                var command = new CreateUserCommand()
                {
                    Username  = request.Username,
                    Password  = request.Password,
                    CreatedBy = ClaimsUtility.GetId(User)
                };
                var result = await Mediator.Send(command);

                return(Ok(new HttpCommandResult <User>("user", result, null)));
            }
            catch (BaseException e)
            {
                Logger.LogError(e.Message);
                stopwatch.Stop();
                return(BadRequest(e.ToExceptionResult(stopwatch.ElapsedMilliseconds)));
            }
        }
Пример #27
0
        public async Task GenerateClientEndpoint(string userId, Claim[] claims, string appName)
        {
            var endpoints  = FakeEndpointUtils.GetFakeEndpoint(3).ToArray();
            var routerMock = new Mock <IEndpointRouter>();

            routerMock.SetupSequence(router => router.GetNegotiateEndpoint(null, endpoints))
            .Returns(endpoints[0])
            .Returns(endpoints[1])
            .Returns(endpoints[2]);
            var router   = routerMock.Object;
            var provider = new ServiceCollection().AddSignalRServiceManager()
                           .Configure <ServiceManagerOptions>(o =>
            {
                o.ApplicationName  = appName;
                o.ServiceEndpoints = endpoints;
            })
                           .AddSingleton(router).BuildServiceProvider();
            var negotiateProcessor = provider.GetRequiredService <NegotiateProcessor>();

            for (int i = 0; i < 3; i++)
            {
                var negotiationResponse = await negotiateProcessor.NegotiateAsync(HubName, null, userId, claims, _tokenLifeTime);

                var tokenString = negotiationResponse.AccessToken;
                var token       = JwtTokenHelper.JwtHandler.ReadJwtToken(tokenString);

                string expectedToken = JwtTokenHelper.GenerateJwtBearer(ClientEndpointUtils.GetExpectedClientEndpoint(HubName, appName, endpoints[i].Endpoint), ClaimsUtility.BuildJwtClaims(null, userId, () => claims), token.ValidTo, token.ValidFrom, token.ValidFrom, endpoints[i].AccessKey);

                Assert.Equal(ClientEndpointUtils.GetExpectedClientEndpoint(HubName, appName, endpoints[i].Endpoint), negotiationResponse.Url);
                Assert.Equal(expectedToken, tokenString);
            }
        }
Пример #28
0
        public async Task <IActionResult> CompleteAssignment(Guid id, CompleteStepVM commandVM)
        {
            //TODO check that the bot who is updating is the same as the one who was assigned

            if (commandVM.Status == StepStatuses.Suspended)
            {
                var result = await Mediator.Send(new SuspendStepCommand()
                {
                    StepId         = id,
                    CreatedBy      = ClaimsUtility.GetId(User),
                    SuspendedUntil = DateTime.Now.AddMilliseconds(_option.DefaultSuspensionTimeMs)
                });

                if (result.ObjectRefId != "")
                {
                    var resolvedStep = (await Mediator.Send(new GetEntityQuery <Step>()
                    {
                        Expression = s => s.Id == new Guid(result.ObjectRefId)
                    })).Result;
                    return(Ok(new HttpCommandResult <Step>("step", result, resolvedStep)));
                }
                else
                {
                    return(Ok(new HttpCommandResult <Step>("", result, null)));
                }
            }
            else
            {
                var completeStepCommand = new CompleteStepCommand()
                {
                    Id         = id,
                    Status     = commandVM.Status.ToLower(),
                    StatusCode = commandVM.StatusCode,
                    Log        = commandVM.Logs,
                    Outputs    = commandVM.Outputs,
                    CreatedBy  = ClaimsUtility.GetId(User),
                    BotId      = new Guid(ClaimsUtility.GetId(User))
                };
                try
                {
                    var result = await Mediator.Send(completeStepCommand);

                    if (result.ObjectRefId != "")
                    {
                        var resolvedStep = (await Mediator.Send(new GetEntityQuery <Step>()
                        {
                            Expression = s => s.Id == new Guid(result.ObjectRefId)
                        })).Result;
                        return(Ok(new HttpCommandResult <Step>("step", result, resolvedStep)));
                    }
                    else
                    {
                        return(Ok(new HttpCommandResult <Step>("", result, null)));
                    }
                }
                catch (DuplicateStepUpdateException exception)
                {
                    return(Ok(new HttpCommandResult <Step>("step", new CommandResult()
                    {
                        Type = CommandResultTypes.None
                    }, (await Mediator.Send(new GetEntityQuery <Step>()
                    {
                        Expression = s => s.Id == id
                    })).Result)));
                }
            }
        }