lib/gds_api/asset_manager.rb



require_relative "base"
require_relative "exceptions"

# @api documented
class GdsApi::AssetManager < GdsApi::Base
  # Creates an asset given a hash with one +file+ attribute
  #
  # Makes a +POST+ request to the asset manager api to create an asset.
  #
  # The asset must be provided as a +Hash+ with a +file+ attribute that
  # behaves like a +File+ object. The +content-type+ that the asset manager will
  # subsequently serve will be based on the file's extension (derived from
  # +#path+). If you supply a +content-type+ via, for example
  # +ActionDispatch::Http::UploadedFile+ or another multipart wrapper, it will
  # be ignored. To provide a +content-type+ directly you must be specify it
  # as a +content_type+ attribute of the hash.
  #
  # @param asset [Hash] The attributes for the asset to send to the api. Must
  #   contain +file+, which behaves like a +File+. All other attributes will be
  #   ignored.
  # @return [GdsApi::Response] The wrapped http response from the api. Behaves
  #   both as a +Hash+ and an +OpenStruct+, and responds to the following:
  #     :id           the URL of the asset
  #     :name         the filename of the asset that will be served
  #     :content_type the content_type of the asset
  #     :file_url     the URL from which the asset will be served when it has
  #                   passed a virus scan
  #     :state        One of 'unscanned', 'clean', or 'infected'. Unless the state is
  #                   'clean' the asset at the :file_url will 404
  #
  # @raise [HTTPErrorResponse] if the request returns an error
  #
  # @example Upload a file from disk
  #   response = asset_manager.create_asset(file: File.new('image.jpg', 'r'))
  #   response['id']           #=> "http://asset-manager.dev.gov.uk/assets/576bbc52759b74196b000012"
  #   response['content_type'] #=> "image/jpeg"
  # @example Upload a file from a Rails param, (typically a multipart wrapper)
  #    params[:file] #=> #<ActionDispatch::Http::UploadedFile:0x007fc60b43c5c8
  #                      # @content_type="application/foofle",
  #                      # @original_filename="cma_case_image.jpg",
  #                      # @tempfile="spec/support/images/cma_case_image.jpg">
  #
  #    # Though we sent a file with a +content_type+ of 'application/foofle',
  #    # this was ignored
  #    response = asset_manager.create_asset(file: params[:file])
  #    response['content_type'] #=> "image/jpeg"
  def create_asset(asset)
    post_multipart("#{base_url}/assets", asset:)
  end

  # Updates an asset given a hash with one +file+ attribute
  #
  # Makes a +PUT+ request to the asset manager api to update an asset.
  #
  # The asset must be provided as a +Hash+ with a +file+ attribute that
  # behaves like a +File+ object. The +content-type+ of the file will be based
  # on the files extension unless you specify a +content_type+ attribute of
  # the hash to set it.
  #
  # @param id [String] The asset identifier (a UUID).
  # @param asset [Hash] The attributes for the asset to send to the api. Must
  #   contain +file+, which behaves like a +File+. All other attributes will be
  #   ignored.
  # @return [GdsApi::Response] The wrapped http response from the api. Behaves
  #   both as a +Hash+ and an +OpenStruct+, and responds to the following:
  #     :id           the URL of the asset
  #     :name         the filename of the asset that will be served
  #     :content_type the content_type of the asset
  #     :file_url     the URL from which the asset will be served when it has
  #                   passed a virus scan
  #     :state        One of 'unscanned', 'clean', or 'infected'. Unless the state is
  #                   'clean' the asset at the :file_url will 404
  #
  # @raise [HTTPErrorResponse] if the request returns an error
  # @example Update a file from disk
  #   uuid = '594602dd-75b3-4e6f-b5d1-cacf8c4d4164'
  #   asset_manager.update_asset(uuid, file: File.new('image.jpg', 'r'))
  def update_asset(id, asset)
    put_multipart("#{base_url}/assets/#{id}", asset:)
  end

  # Fetches an asset's metadata given the id
  #
  # @param id [String] The asset identifier (a UUID).
  # @return [GdsApi::Response, nil] A response object containing the parsed JSON response. If
  #   the asset cannot be found, +nil+ wil be returned.
  #
  # @raise [HTTPErrorResponse] if the request returns an error
  def asset(id)
    get_json("#{base_url}/assets/#{id}")
  end

  # Deletes an asset given an id
  #
  # Makes a +DELETE+ request to the asset manager api to delete an asset.
  #
  # @param id [String] The asset identifier (a UUID).
  # @return [GdsApi::Response] The wrapped http response from the api. Behaves
  #   both as a +Hash+ and an +OpenStruct+, and responds to the following:
  #     :id           the URL of the asset
  #     :name         the filename of the asset that will be served
  #     :content_type the content_type of the asset
  #     :file_url     the URL from which the asset will be served when it has
  #                   passed a virus scan
  #     :state        One of 'unscanned', 'clean', or 'infected'. Unless the state is
  #                   'clean' the asset at the :file_url will 404
  #
  # @raise [HTTPErrorResponse] if the request returns an error
  # @example Delete a file from disk
  #   uuid = '594602dd-75b3-4e6f-b5d1-cacf8c4d4164'
  #   asset_manager.delete_asset(uuid)
  def delete_asset(id)
    delete_json("#{base_url}/assets/#{id}")
  end

  # Restores an asset given an id
  #
  # Makes a +POST+ request to the asset manager api to restore an asset.
  #
  # @param id [String] The asset identifier (a UUID).
  # @return [GdsApi::Response] The wrapped http response from the api. Behaves
  #   both as a +Hash+ and an +OpenStruct+, and responds to the following:
  #     :id           the URL of the asset
  #     :name         the filename of the asset that will be served
  #     :content_type the content_type of the asset
  #     :file_url     the URL from which the asset will be served when it has
  #                   passed a virus scan
  #     :state        One of 'unscanned', 'clean', or 'infected'. Unless the state is
  #                   'clean' the asset at the :file_url will 404
  #
  # @raise [HTTPErrorResponse] if the request returns an error
  # @example Restore a deleted file
  #   uuid = '594602dd-75b3-4e6f-b5d1-cacf8c4d4164'
  #   asset_manager.restore_asset(uuid)
  def restore_asset(id)
    post_json("#{base_url}/assets/#{id}/restore")
  end

  # Fetches a Whitehall asset given the legacy URL path
  #
  # @param legacy_url_path [String] The Whitehall asset identifier.
  # @return [GdsApi::Response] A response object containing the raw asset.
  #   If the asset cannot be found, +GdsApi::HTTPNotFound+ will be raised.
  #
  # @raise [HTTPErrorResponse] if the request returns an error
  def whitehall_media(legacy_url_path)
    get_raw("#{base_url}/#{uri_encode(legacy_url_path)}")
  end

  # Fetches an asset given the id and filename
  #
  # @param id [String] The asset identifier.
  # @param filename [String] Filename of the asset.
  # @return [GdsApi::Response] A response object containing the raw asset.
  #   If the asset cannot be found, +GdsApi::HTTPNotFound+ will be raised.
  #
  # @raise [HTTPErrorResponse] if the request returns an error
  def media(id, filename)
    get_raw("#{base_url}/media/#{id}/#{filename}")
  end

private

  def base_url
    endpoint
  end
end