/**
   * Gets the details for a provenance event.
   *
   * @param id The id of the event
   * @param clusterNodeId The id of node in the cluster that the event/flowfile originated from.
   *     This is only required when clustered.
   * @return A provenanceEventEntity
   */
  @GET
  @Consumes(MediaType.WILDCARD)
  @Produces(MediaType.APPLICATION_JSON)
  @Path("{id}")
  // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE')")
  @ApiOperation(
      value = "Gets a provenance event",
      response = ProvenanceEventEntity.class,
      authorizations = {@Authorization(value = "Provenance", type = "ROLE_PROVENANCE")})
  @ApiResponses(
      value = {
        @ApiResponse(
            code = 400,
            message =
                "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
        @ApiResponse(code = 401, message = "Client could not be authenticated."),
        @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
        @ApiResponse(code = 404, message = "The specified resource could not be found."),
        @ApiResponse(
            code = 409,
            message =
                "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
      })
  public Response getProvenanceEvent(
      @ApiParam(
              value = "The id of the node where this event exists if clustered.",
              required = false)
          @QueryParam("clusterNodeId")
          final String clusterNodeId,
      @ApiParam(value = "The provenence event id.", required = true) @PathParam("id")
          final LongParameter id) {

    // ensure the id is specified
    if (id == null) {
      throw new IllegalArgumentException("Provenance event id must be specified.");
    }

    // replicate if cluster manager
    if (isReplicateRequest()) {
      // since we're cluster we must specify the cluster node identifier
      if (clusterNodeId == null) {
        throw new IllegalArgumentException("The cluster node identifier must be specified.");
      }

      return replicate(HttpMethod.GET, clusterNodeId);
    }

    // get the provenance event
    final ProvenanceEventDTO event = serviceFacade.getProvenanceEvent(id.getLong());
    event.setClusterNodeId(clusterNodeId);

    // create a response entity
    final ProvenanceEventEntity entity = new ProvenanceEventEntity();
    entity.setProvenanceEvent(event);

    // generate the response
    return clusterContext(generateOkResponse(entity)).build();
  }
  /**
   * Gets the content for the input of the specified event.
   *
   * @param clusterNodeId The id of the node within the cluster this content is on. Required if
   *     clustered.
   * @param id The id of the provenance event associated with this content.
   * @return The content stream
   */
  @GET
  @Consumes(MediaType.WILDCARD)
  @Produces(MediaType.WILDCARD)
  @Path("{id}/content/input")
  // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE')")
  @ApiOperation(
      value = "Gets the input content for a provenance event",
      authorizations = {@Authorization(value = "Provenance", type = "ROLE_PROVENANCE")})
  @ApiResponses(
      value = {
        @ApiResponse(
            code = 400,
            message =
                "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
        @ApiResponse(code = 401, message = "Client could not be authenticated."),
        @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
        @ApiResponse(code = 404, message = "The specified resource could not be found."),
        @ApiResponse(
            code = 409,
            message =
                "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
      })
  public Response getInputContent(
      @ApiParam(
              value = "The id of the node where the content exists if clustered.",
              required = false)
          @QueryParam("clusterNodeId")
          final String clusterNodeId,
      @ApiParam(value = "The provenance event id.", required = true) @PathParam("id")
          final LongParameter id) {

    // ensure proper input
    if (id == null) {
      throw new IllegalArgumentException("The event id must be specified.");
    }

    // replicate if cluster manager
    if (isReplicateRequest()) {
      // determine where this request should be sent
      if (clusterNodeId == null) {
        throw new IllegalArgumentException("The id of the node in the cluster is required.");
      } else {
        return replicate(HttpMethod.GET, clusterNodeId);
      }
    }

    // get the uri of the request
    final String uri =
        generateResourceUri(
            "provenance", "events", String.valueOf(id.getLong()), "content", "input");

    // get an input stream to the content
    final DownloadableContent content =
        serviceFacade.getContent(id.getLong(), uri, ContentDirection.INPUT);

    // generate a streaming response
    final StreamingOutput response =
        new StreamingOutput() {
          @Override
          public void write(OutputStream output) throws IOException, WebApplicationException {
            try (InputStream is = content.getContent()) {
              // stream the content to the response
              StreamUtils.copy(is, output);

              // flush the response
              output.flush();
            }
          }
        };

    // use the appropriate content type
    String contentType = content.getType();
    if (contentType == null) {
      contentType = MediaType.APPLICATION_OCTET_STREAM;
    }

    return generateOkResponse(response)
        .type(contentType)
        .header(
            "Content-Disposition",
            String.format("attachment; filename=\"%s\"", content.getFilename()))
        .build();
  }
Example #3
0
  /**
   * Removes the specified access policy.
   *
   * @param httpServletRequest request
   * @param version The revision is used to verify the client is working with the latest version of
   *     the flow.
   * @param clientId Optional client id. If the client id is not specified, a new one will be
   *     generated. This value (whether specified or generated) is included in the response.
   * @param id The id of the access policy to remove.
   * @return A entity containing the client id and an updated revision.
   */
  @DELETE
  @Consumes(MediaType.WILDCARD)
  @Produces(MediaType.APPLICATION_JSON)
  @Path("{id}")
  // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
  @ApiOperation(
      value = "Deletes an access policy",
      response = AccessPolicyEntity.class,
      authorizations = {@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")})
  @ApiResponses(
      value = {
        @ApiResponse(
            code = 400,
            message =
                "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
        @ApiResponse(code = 401, message = "Client could not be authenticated."),
        @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
        @ApiResponse(code = 404, message = "The specified resource could not be found."),
        @ApiResponse(
            code = 409,
            message =
                "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
      })
  public Response removeAccessPolicy(
      @Context final HttpServletRequest httpServletRequest,
      @ApiParam(
              value =
                  "The revision is used to verify the client is working with the latest version of the flow.",
              required = false)
          @QueryParam(VERSION)
          final LongParameter version,
      @ApiParam(
              value =
                  "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.",
              required = false)
          @QueryParam(CLIENT_ID)
          @DefaultValue(StringUtils.EMPTY)
          final ClientIdParameter clientId,
      @ApiParam(value = "The access policy id.", required = true) @PathParam("id")
          final String id) {

    if (isReplicateRequest()) {
      return replicate(HttpMethod.DELETE);
    }

    // handle expects request (usually from the cluster manager)
    final Revision revision =
        new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
    return withWriteLock(
        serviceFacade,
        revision,
        lookup -> {
          final Authorizable accessPolicy = lookup.getAccessPolicyById(id);
          accessPolicy.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
        },
        () -> {},
        () -> {
          // delete the specified access policy
          final AccessPolicyEntity entity = serviceFacade.deleteAccessPolicy(revision, id);
          return clusterContext(generateOkResponse(entity)).build();
        });
  }
  /**
   * Removes the specified input port.
   *
   * @param httpServletRequest request
   * @param version The revision is used to verify the client is working with the latest version of
   *     the flow.
   * @param clientId Optional client id. If the client id is not specified, a new one will be
   *     generated. This value (whether specified or generated) is included in the response.
   * @param id The id of the input port to remove.
   * @return A inputPortEntity.
   */
  @DELETE
  @Consumes(MediaType.WILDCARD)
  @Produces(MediaType.APPLICATION_JSON)
  @Path("{id}")
  // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
  @ApiOperation(
      value = "Deletes an input port",
      response = InputPortEntity.class,
      authorizations = {@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")})
  @ApiResponses(
      value = {
        @ApiResponse(
            code = 400,
            message =
                "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
        @ApiResponse(code = 401, message = "Client could not be authenticated."),
        @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
        @ApiResponse(code = 404, message = "The specified resource could not be found."),
        @ApiResponse(
            code = 409,
            message =
                "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
      })
  public Response removeInputPort(
      @Context HttpServletRequest httpServletRequest,
      @ApiParam(
              value =
                  "The revision is used to verify the client is working with the latest version of the flow.",
              required = false)
          @QueryParam(VERSION)
          LongParameter version,
      @ApiParam(
              value =
                  "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.",
              required = false)
          @QueryParam(CLIENT_ID)
          @DefaultValue(StringUtils.EMPTY)
          ClientIdParameter clientId,
      @ApiParam(value = "The input port id.", required = true) @PathParam("id") String id) {

    // replicate if cluster manager
    if (properties.isClusterManager()) {
      return clusterManager
          .applyRequest(
              HttpMethod.DELETE, getAbsolutePath(), getRequestParameters(true), getHeaders())
          .getResponse();
    }

    // handle expects request (usually from the cluster manager)
    final String expects = httpServletRequest.getHeader(WebClusterManager.NCM_EXPECTS_HTTP_HEADER);
    if (expects != null) {
      serviceFacade.verifyDeleteInputPort(id);
      return generateContinueResponse().build();
    }

    // determine the specified version
    Long clientVersion = null;
    if (version != null) {
      clientVersion = version.getLong();
    }

    // delete the specified input port
    final ConfigurationSnapshot<Void> controllerResponse =
        serviceFacade.deleteInputPort(new Revision(clientVersion, clientId.getClientId()), id);

    // get the updated revision
    final RevisionDTO revision = new RevisionDTO();
    revision.setClientId(clientId.getClientId());
    revision.setVersion(controllerResponse.getVersion());

    // build the response entity
    final InputPortEntity entity = new InputPortEntity();
    entity.setRevision(revision);

    return clusterContext(generateOkResponse(entity)).build();
  }