/**
   * Add new authentication execution to a flow
   *
   * @param flowAlias Alias of parent flow
   * @param data New execution JSON data containing 'provider' attribute
   */
  @Path("/flows/{flowAlias}/executions/execution")
  @POST
  @NoCache
  @Consumes(MediaType.APPLICATION_JSON)
  public void addExecution(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
    auth.requireManage();

    AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
    if (parentFlow == null) {
      throw new BadRequestException("Parent flow doesn't exists");
    }
    if (parentFlow.isBuiltIn()) {
      throw new BadRequestException("It is illegal to add execution to a built in flow");
    }
    String provider = data.get("provider");

    // make sure provider is one of the registered providers
    ProviderFactory f;
    if (parentFlow.getProviderId().equals(AuthenticationFlow.CLIENT_FLOW)) {
      f =
          session
              .getKeycloakSessionFactory()
              .getProviderFactory(ClientAuthenticator.class, provider);
    } else if (parentFlow.getProviderId().equals(AuthenticationFlow.FORM_FLOW)) {
      f = session.getKeycloakSessionFactory().getProviderFactory(FormAction.class, provider);
    } else {
      f = session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, provider);
    }
    if (f == null) {
      throw new BadRequestException("No authentication provider found for id: " + provider);
    }

    AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
    execution.setParentFlow(parentFlow.getId());
    execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
    execution.setAuthenticatorFlow(false);
    execution.setAuthenticator(provider);
    execution.setPriority(getNextPriority(parentFlow));

    execution = realm.addAuthenticatorExecution(execution);

    data.put("id", execution.getId());
    adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
  }
 protected void copy(String newName, AuthenticationFlowModel from, AuthenticationFlowModel to) {
   for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(from.getId())) {
     if (execution.isAuthenticatorFlow()) {
       AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId());
       AuthenticationFlowModel copy = new AuthenticationFlowModel();
       copy.setAlias(newName + " " + subFlow.getAlias());
       copy.setDescription(subFlow.getDescription());
       copy.setProviderId(subFlow.getProviderId());
       copy.setBuiltIn(false);
       copy.setTopLevel(false);
       copy = realm.addAuthenticationFlow(copy);
       execution.setFlowId(copy.getId());
       copy(newName, subFlow, copy);
     }
     execution.setId(null);
     execution.setParentFlow(to.getId());
     realm.addAuthenticatorExecution(execution);
   }
 }
  /**
   * Add new authentication execution
   *
   * @param execution JSON model describing authentication execution
   */
  @Path("/executions")
  @POST
  @NoCache
  @Consumes(MediaType.APPLICATION_JSON)
  public Response addExecution(AuthenticationExecutionRepresentation execution) {
    auth.requireManage();

    AuthenticationExecutionModel model = RepresentationToModel.toModel(realm, execution);
    AuthenticationFlowModel parentFlow = getParentFlow(model);
    if (parentFlow.isBuiltIn()) {
      throw new BadRequestException("It is illegal to add execution to a built in flow");
    }
    model.setPriority(getNextPriority(parentFlow));
    model = realm.addAuthenticatorExecution(model);

    adminEvent
        .operation(OperationType.CREATE)
        .resourcePath(uriInfo, model.getId())
        .representation(execution)
        .success();
    return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
  }
  /**
   * Add new flow with new execution to existing flow
   *
   * @param flowAlias Alias of parent authentication flow
   * @param data New authentication flow / execution JSON data containing 'alias', 'type',
   *     'provider', and 'description' attributes
   */
  @Path("/flows/{flowAlias}/executions/flow")
  @POST
  @NoCache
  @Consumes(MediaType.APPLICATION_JSON)
  public void addExecutionFlow(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
    auth.requireManage();

    AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
    if (parentFlow == null) {
      throw new BadRequestException("Parent flow doesn't exists");
    }
    String alias = data.get("alias");
    String type = data.get("type");
    String provider = data.get("provider");
    String description = data.get("description");

    AuthenticationFlowModel newFlow = realm.getFlowByAlias(alias);
    if (newFlow != null) {
      throw new BadRequestException("New flow alias name already exists");
    }
    newFlow = new AuthenticationFlowModel();
    newFlow.setAlias(alias);
    newFlow.setDescription(description);
    newFlow.setProviderId(type);
    newFlow = realm.addAuthenticationFlow(newFlow);
    AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
    execution.setParentFlow(parentFlow.getId());
    execution.setFlowId(newFlow.getId());
    execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
    execution.setAuthenticatorFlow(true);
    execution.setAuthenticator(provider);
    execution.setPriority(getNextPriority(parentFlow));
    execution = realm.addAuthenticatorExecution(execution);

    data.put("id", execution.getId());
    adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
  }