Follow up for #1776796: Provide a better UX for creating, editing & managing draft revisions.

Problem/Motivation

When access workflow is in place, the fixed public / private sorage configuration is a problem:

  • If site owner chooses public file storage, they suffer from PSA-2016-003
  • If site owner chooses private file storage, they suffer from performance penalty. For example, on a campaign page with 50ish anonymous-user-submitted-and-reviewed testimonial photos, serving the page needs 51 Drupal bootstraps

Because of the performance cost of private files, a lot of websites use public files by default and sometimes involuntarily expose files.

Proposed resolution

These contrib modules implement a solution as a POC:

The basic idea is to check if a file can be accessed by anonymous users and move accordingly.
This could be implemented as a third option on file fields. (We probably should keep allowing to force public or private file storage.)

Comments

tstoeckler’s picture

In theory I agree that this would make lots of sense. The problem is that idea of "published"/"unpublished" is not common among all entity types but specific to nodes. File handling on nodes is managed by the file field, though, which is entity-type agnostic.

Now node.module *could* alter the file field form and hook into the field behavior, but...

agentrickard’s picture

This idea comes up a lot in our D7 projects, but I'm not sure how feasible it actually is. Some of the moving parts are:

  1. What do we do to the current (arguably broken) garbage collection that removes files on unpublished nodes?
  2. Is it possible to move a file from private to public? (Let's assume that is technically feasible.)
  3. How do field settings (e.g. default file field as public/private) affect this behavior?
  4. What UI signals do we give to editors about file status?
  5. Does that work with remote files (and do we care)?
  6. In a scenario where a file can be attached to multiple entities, how do you enforce privacy?
  7. When using a WYSIWYG, how is file usage tracked, especially if we have WYSIWYG in core?
  8. How do we allow preview of files to the "right" users?

Given the state of D8 feature freeze, I would suggest that the best we can do is allow this behavior to be defined in contrib, which means attacking only the garbage collection and possibly the WYSIWYG in this issue.

hass’s picture

Well this are some good questions.

I mainly think about the following critical issues:

  • A lawyer sends you are warning letter that you need to immediately remove some illegally used images/videos from your website. Your are running Workbench Suite or other revision system and you cannot remove the files because they are still attached to an unpublished version. We cannot solve this today as I know except deleting the node with all versions.
  • You are preparing press releases of a future product and this should for sure not seen by anybody in the public and it has attachments. Just think how secure Apple takes their hardware releases. Nothing is allowed to be public.

If an attachment is already public in other content, it makes not sense to move around :-). I'm sure with some brainstorming we will find more examples why we need this. Adding a .htaccess files cannot really solve the issue as it does not work on IIS out of the box.

agentrickard’s picture

Right, and I think a contrib workflow module can handle that if we solve problem 1 (bad garbage collection) and problem 2 (actually moving files from private:// to public://) and possibly problem 7 (WYSIWYG).

hass’s picture

#2. Just a copy/move :-)
#7. Looks likely to be solved with UUIDs in D8 core if I remember correctly.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

technikh’s picture

Any solution for this? I am looking for a solution in my D8 site.

szato’s picture

Issue summary: View changes

Our working D8 solution for the mentioned problem:
1) Move public files to private - to be able to manage file access.
2) Add entity_usage module with "Track file/image fields" patch to track images, files too. It works for WYSIWYG files too.
3) Implement your custom file access management based on entity_usage data with hooks: hook_file_access() (hook_ENTITY_TYPE_access) for referenced files and hook_file_download() for WYSIWYG files.

In 3) we are checking entity (node) view access to nodes from which is the file referenced. If at least one node view access is granted, we return AccessResult::allowed(), otherwise AccessResult::forbidden().

szato’s picture

Issue summary: View changes

If you need tracking non-linked images added with CKEditor Image plugin, add "Add plugin for tracking (non linked) images inserted with WYSIWYG Image" patch.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

claudiu.cristea’s picture

Version: 9.4.x-dev » 10.1.x-dev

@szato, your solution works but files in the private file system are expensive. Each file download requires PHP processing. A public file is just served by the webserver or frontend cache and that's a relief for Drupal/PHP

berdir’s picture

You can combine that with moving files between private and public, so you only need to do access checks as long as there is no public content using them. Not saying it's trivial to do that, at least not in a generic way, but it's... possible.

claudiu.cristea’s picture

@Berdir, yes, I was thinking on a solution which combines both. I'm wondering whether such a feature could be made generic enough to create a contrib module.

berdir’s picture

Maybe, if you check for access on any referenced entity for an anonymous user? And you probably also want to specifically handle media entities, so check the nodes/entities using the media, not just the media entity. Which means you need to depend on the entity_usage module as mentioned above (although possible a combination of both file usage and entity usage, to not require that patch).

claudiu.cristea’s picture

@Berdir, it would be great if you have some time to review a first approach at https://www.drupal.org/project/unpublished_file

Not yet done: "check the nodes/entities using the media, not just the media entity" not implemented yet.

EDIT: See #26

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

claudiu.cristea’s picture

OK, I have a complete solution but in an early stage of development, the File Visibility module.

Solution from #24 is abandoned.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

geek-merlin’s picture

Title: Unpublished content and attachments should be kept private » Unpublished files should be in private storage
Related issues: +#2904842: Make private file access handling respect the full entity reference chain, +#3087660: Automatically move files to public / private storage, depending on referencing entities' access

Coming from #3087660: Automatically move files to public / private storage, depending on referencing entities' access and #2904842: Make private file access handling respect the full entity reference chain, which lived for quite some time as a dup of this issue.
Maybe the title of this issue is not really perfect. Updating it accordingly (ymmv).

@claudiu, kudos for the file_visibility module!
It looks far more feature-rich and elaborated than my file_access_fix that i created some time ago and roughly corresponds to your unpublished_file POC.

So i am deprecating my module in favor of yours.

dqd’s picture

I think the new issue title is a little bit blurry now. From a UX point of view a "file" can not be set "(un)published" in Drupal core yet in the same sense like content, but an entity holding a file, like media or nodes with image fields, or nodes with body embedded images can.

There is another issue with unpublished (media) entities holding files not being 100% unpublished in references. Which is another issue in core, but out of the scope of this issue.

From my understanding this issue here is about the file accessibility in connection with unpublished entities referencing the file, where files (not media) keep being accessible even if unused or being part of unpublished content (references). The title should follow this a little bit clearer to distinguish between these both issues. The later isn't probably even not documented yet (I will take a look next days).

Another contrib project not mentioned yet in this scope: https://www.drupal.org/project/file_unpublish