Problem/Motivation

We have an intranet site that uses Acquia DAM to serve assets like images and documents. Currently, the site uses the media_acquiadam module. The file fields on our media types are implemented using the private filesystem. Since that module downloads the file to the server, the proper permissions are maintained. Even if a user were to right click on an image on the site and copy the URL, it would be inaccessible to unauthenticated users.

Does this module support the private filesystem or a similar means for restriction access? While trying to migrate our existing site and assets to acquia_dam, I'm struggling to find a way to set up similar access restrictions. Since there is not a traditional file field, what would be the best way to go about this?

Steps to reproduce

  1. Set up a site with a connection to Acquia DAM using this module
  2. Embed an image into your site via the WYSIWYG editor or an entity reference field
  3. View the media entity
  4. Right click the image file
  5. Observe the URL is of the pattern https://<subdomain>.widen.net/content/gxzcvxtogx/web/test-image-scenario.jpg
  6. Paste this URL into an incognito window
  7. Observe you are able to see the image without being logged into Drupal

Proposed resolution

  • For previous projects, I've implemented an EventSubscriber that returns a BinaryFileResponse when viewing the media entity's canonical path. This obscures the file path on the server and allows a path alias to be used for direct access of the file. I'm able to use a TrustedRedirectResponse with `acquia_dam` but the user is redirected to a Widen CDN link. I could temporarily fetch and save the file to use a BinaryFileResponse, but there could be performance implications.
  • I've not developed or implemented a custom stream wrapper, but there may be a possibility of extending it.

Remaining tasks

n/a

User interface changes

n/a

API changes

n/a

Data model changes

n/a

Issue fork acquia_dam-3369081

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

patrickfweston created an issue. See original summary.

patrickfweston’s picture

Title: Support for private files system » Support for private files system, or similar access restriction
patrickfweston’s picture

I was actually able to get a proof of concept working where the path alias of the media entity is used, but the image content is displayed inline in the browser.

Here's what my EventSubscriber looks like:

  public function onRequest(RequestEvent $event) {
    // Get values from the request.
    $attributes = $event->getRequest()->attributes;
    $media = $attributes->get('media');
    $route_name = $attributes->get('_route');

    // Redirect to the file directly if we are accessing a media entity's full
    // view mode route.
    $view_mode = $attributes->get("view_mode");
    if ($media && !str_contains($route_name, 'media_entity_download') && $route_name && $view_mode === 'full') {
      // Get the source for this media entity.
      $source = $media->getSource();

      // Grab the ID values from the source information to be fetched from the
      // Acquia DAM.
      $id_values = $source->getSourceFieldValue($media);

      // Get the client for the Acquia DAM and get the asset object.
      $client = \Drupal::service('acquia_dam.client.factory')->getSiteClient();
      $asset = $client->getAsset($id_values['asset_id'], $id_values['version_id'] ?? '');

      // Get the embed URL for the asset.
      $url = $asset["embeds"]["original"]["url"];

      // Create a response with the URL's content.
      $response = new Response(file_get_contents($url));

      // Create the disposition of the file to display it inline.
      $disposition = $response->headers->makeDisposition(
        ResponseHeaderBag::DISPOSITION_INLINE,
        $asset['filename']
      );

      // Create the MIME type from the Asset's properties.
      $mime_type = $asset["file_properties"]["format_type"] . "/" . $asset["file_properties"]["format"];

      // Initialize headers for the response.
      $headers = [
        'Content-Type' => $mime_type,
        'Content-Disposition' => $disposition . '"',
        'Content-Description' => ' File Transfer',
      ];

      // Return the response object.
      $response->headers->add($headers);
      $response->setStatusCode(Response::HTTP_OK);

      // Dispatch request
      $event->setResponse($response);
    }
  }
mglaman’s picture

Version: 1.0.8 » 1.0.x-dev
Category: Support request » Feature request

Tagging as a feature request, we'll raise internally.

rajeshreeputra’s picture

@patrickfweston - can you try 1.1.x version with download and sync option enabled?

danflanagan8’s picture

I'm running into a similar but simpler issue. I need sync'ed files to be stored in the private file system. I tried a hook_entity_field_storage_info_alter assuming that setting the file field to private would do the trick:

/**
 * Implements hook_entity_field_storage_info_alter().
 */
function my_module_entity_field_storage_info_alter(&$fields, EntityTypeInterface $entity_type) {
  // Use the private file scheme for DAM media.
  if ($entity_type->id() == 'media' && !empty($fields['acquia_dam_managed_file'])) {
    $fields['acquia_dam_managed_file']->setSetting('uri_scheme', 'private');
  }
}

No joy. Instead, the Drupal\acquia_dam\AssetFileEntityHelper class always uses the default scheme:

    $custom_path = $this->config->get('asset_file_directory_path');
    $scheme = \Drupal::config('system.file')->get('default_scheme');
    $directory = $scheme . '://' . $this->token->replace($custom_path, ['media' => $media_entity]);

It would be great if that were either configurable or if it honored the scheme set on the acquia_dam_managed_file base field.

rajeshreeputra’s picture

Version: 1.0.x-dev » 1.1.x-dev

Yes, that sounds reasonable to me.

rajeshreeputra’s picture

Status: Active » Needs review

Requesting review.

ankitv18’s picture

Status: Needs review » Needs work

Tests are failing, please look into this.

rajeshreeputra’s picture

Status: Needs work » Needs review

Updated scheme_options with stream wrapper WRITE_VISIBLE options.

japerry’s picture

Looking very close, added one comment regarding fetching the default uri_scheme ... it appears the logic is duplicated, and it'd be nice to centralize fetching the default.

amangrover90’s picture

Status: Needs review » Fixed

Merged the changes.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.