Entendiendo el sistema de ficheros de Drupal

drupal-8-file-system.jpg
Solucionex
20
Ene 21

El sistema de ficheros (File System) de Drupal es muy potente, pero para que podamos aprovecharlo, es necesario que entendamos cómo funciona.

Existen muchos tutoriales y guías en las que se explica cómo configurar este sistema: indicar cuál será la carpeta pública y la privada, configurar los campos para que se guarden en una o en otra, qué permisos necesita cada carpeta (aunque existen muchas opiniones encontradas), etc...

El problema es que, si no sabemos cómo funciona y qué implica cada implementación, nos será muy complicado hacer una buena elección y uso de este sistema.

En este post vamos a centrarnos en los dos tipos de almacenamiento (público/privado) de Drupal, su función, las diferencias entre ellos, y algunos posibles casos de uso. No vamos a mirar en detalle cómo configurar los campos de tipo imagen o fichero, módulo media, permisos, etc.

 

Almacenamiento de ficheros en Drupal, Public vs Private

Drupal nos permite tener dos directorios en los que almacenar nuestros archivos: un directorio público y un directorio privado.

La configuración de estos directorios se hace, por defecto, en el archivo 'settings.php', aunque en versiones anteriores se permitía su configuración desde site-building.

Esta configuración es muy simple, lo único que tenemos que indicar es qué directorio queremos usar para cada sistema. Por defecto, se suele usar la siguiente configuración:

    $settings['file_public_path'] = 'sites/default/files';

    $settings['file_private_path'] = '../private';


Como podemos ver, hemos indicado que los ficheros públicos se almacenarán dentro de '/web/sites/default/files', y los privados dentro de '/private', al mismo nivel que web. Esto es muy importante, ya que no queremos que nuestros ficheros privados se encuentren dentro del directorio web, para poder restringir su acceso de forma correcta.

Drupal sólo necesita que tengamos configurado el sistema de ficheros público. Aquí se almacenarán, por defecto, las imágenes, documentos, o cualquier otro tipo de archivos que se suban al portal. Pero no sólo eso, también es posible que se almacenen ficheros de CSS, JS, o cualquier otro que el portal web necesite acceder de forma pública.


Public

Los ficheros que almacenemos como públicos serán, por defecto, accesibles para todo el mundo. Cualquier usuario del portal podrá verlos sin necesidad de permisos especiales.

Utilicemos como ejemplo un contenido ficticio 'Noticia'. Este contenido tiene varios campos, entre ellos un campo 'Adjunto' que se corresponde a un campo de tipo File (podría ser perfectamente un campo de tipo Media), para poder subir un PDF adjunto a la noticia. El campo lo hemos configurado como Público. Qué implica esto?

El escenario típico es que la noticia esté publicada y exista un enlace a dicho documento. El enlace nos abrirá el fichero en la dirección que tengamos indicada como directorio público, por defecto en '/sites/default/files/.../adjunto.pdf'. Cualquier usuario tendrá acceso a este documento y, además, podrá compartir la URL, ya que es la dirección real del fichero.

Qué pasa si despublicamos la noticia? El fichero seguirá siendo accesible para quienes conozcan la URL, ya que el acceso a este directorio es público. Aquí está la principal diferencia entre el almacenamiento público y el privado, y lo que hace que su conocimiento sea tan útil.


Private

Vamos a utilizar el mismo ejemplo que para Public, una noticia con un campo 'Adjunto'.

Esta vez, en la configuración del campo (si utilizamos Media debemos configurarlo en la propia entidad de Media), le indicamos que utilice el almacenamiento privado. Es necesario haber configurado este almacenamiento en el 'settings.php' para que esto funcione, claro.

Tenemos ahora una noticia creada, publicada, con el campo 'Adjunto' privado, por lo que... ¿cuál es la diferencia?

A primera vista, ninguna. El usuario va a poder acceder al documento y no va a notar ninguna diferencia; sigue siendo accesible aunque hayamos indicado que sea 'privado'. Esto puede ser bastante confuso; indicar que el campo de tipo File es privado no significa que el acceso al fichero esté "protegido", pero entonces, ¿qué significa?

La diferencia principal está en lo que pasa cuando despubliquemos la noticia. Una vez la noticia no esté pública, es decir, cuando el usuario no pueda acceder a la noticia, el fichero adjunto también dejará de ser accesible. Aunque el usuario se sepa la URL, Drupal devolverá un error de acceso denegado.

Es decir, el permiso de acceso al fichero depende directamente del permiso de acceso al contenido que lo contiene.

Además, podemos fijarnos en que la URL del fichero ya no se corresponde con la localización real de éste; en vez de estar ubicado en '/sites/default/files/...', la URL será del estilo '/system/files/...'. Ésta URL "no existe", no es un directorio real donde Drupal almacena estos archivos, si no una especie de enlace simbólico que utilizará Drupal para dirigirnos al fichero real.


Casos de uso

Imaginemos que tenemos un tipo de contenido que sólo es acccesible por usuarios que estén identificados en nuestro portal Drupal. Este tipo de contenido contiene un campo en el que se almacenan documentos adjuntos. Qué opción elegimos, almacenamiento público o privado?

  • Público: el contenido sólo es visible por los usuarios identificados, pero si un usuario anónimo tiene la URL de los ficheros adjuntos, podrá acceder a estos.
     
  • Privado: el contenido sólo es visible por los usuarios identificados y, además, los ficheros adjuntos son también sólo accesibles por ellos. Aunque compartan la URL del fichero, no se permitirá el acceso a menos que se esté identificado.

Por la tanto, la elección de qué almacenamiento utilizar dependerá de nuestras necesidades. Ya que se trata de un contenido "privado", lo normal será almacenar los documentos de forma privada, para que compartan los requisitos de accceso con el propio contenido. Aún así, es posible que no nos importe que los documentos sean accesibles, en cuyo caso podríamos elegir el sistema público.

Otro posible uso: tenemos un portal web en el cual los usuarios deben poder subir su Currículum o algún otro fichero confidencial. Qué almacenamiento elegimos?
En este caso parece bastante obvio que debemos elegir el almacenamiento privado, ya que se trata de información confidencial a la que sólo debería poder acceder un número limitado de usuarios. Si almacenamos estos CVs en la carpeta pública, no podemos garantizar su control de acceso; si alguien obtiene o descubre la URL, podrá acceder al documento.

Para este ejemplo en concreto, una solución limpia podría ser tener un campo de tipo File en la entidad User de Drupal. De esta forma, sólo el propio usuario (que tienen acceso a su propio perfil), y los usuarios con permisos de visualización de perfiles ajenos, como un Administrador, podrán ver el CV.

Con lo que hemos visto hasta ahora, podemos cubrir un número muy elevado de posibilidades, pero, ¿qué pasa si necesitamos más control?

 

Control de acceso customizado

Es probable que queramos que un usuario pueda ver un contenido, pero no tenga acceso a los ficheros que éste contenga.

Por ejemplo, queremos que todos los usuarios, incluídos los anónimos, puedan ver los contenidos de tipo Noticia, pero que para poder descargar el documento adjunto tengan que estar identificados.

Esto podemos resolverlo de varias formas, como utilizando algunos hooks que nos proporciona Drupal, y dependerá de la implementación que hayamos realizado (no es lo mismo si es un tipo Media, por ejemplo). No vamos a entrar en detalle en cómo desarrollar este control de acceso, pero sí explicar por dónde podríamos empezar:

  • hook_file_download: Este hook de Drupal nos permite interceptar el acceso a cualquier fichero que esté almacenado en el directorio privado. Cada vez que un usuario acceda a dicho fichero, saltará el hook. Con esto, podemos incluír aquí la lógica que necesitemos: para el ejemplo anterior, podríamos obtener el usuario que ha lanzado la petición, comprobar que esté identificado, y, si no lo está, bloquear su acceso. Este hook es útil para muchas otras cosas, como controlar la cantidad de veces que alguien ha accedido a un fichero, cambiar los headers antes de su descarga, etc...
     
  • hook_entity_access: El hook genérico que controla el acceso a cualquier entidad de Drupal. Al final, los ficheros se "almacenan" dentro de una entidad File, por lo que podemos controlar su acceso como el de cualquier otra entidad. Por comodidad, es más sencillo utilizar el hook específico para Files, hook_file_access. Al ser un hook mucho más genérico que el anterior, debemos realizar más comprobaciones, pero también nos ofrece más posibilidades, ya que nos da aceso a la propia entidad File.
     
  • EntityAccessControlHandler: Sin entrar en detalles de cómo implementarlo, ya que merecería su propio post, otra opción es la creación de un EntityAccessControl custom para nuestros ficheros. Es seguramente la opción más compleja de las vistas, pero también la más moderna y potente. El Core de Drupal tiene su propia implementación de esta clase para la entidad File en '\Core\File\FileAccessControlHandler'; revisarla puede ser muy útil, ya que nos ayuda a entender cómo controla Drupal el acceso y las posibilidades que nos ofrece.
     

 

Como conclusión, el conocimiento de cómo funciona en Drupal el sistema de ficheros y las diferentes opciones que nos proporciona es muy útil, y nos permitirá realizar una selección mucho más informada de cómo debemos almacenar nuestros ficheros según las necesidades existentes.