wazuh-dashboard-plugins icon indicating copy to clipboard operation
wazuh-dashboard-plugins copied to clipboard

Custom branding: assets upload

Open AlexRuiz7 opened this issue 2 years ago • 14 comments

Description

In order to ease the white-label process to the user, file upload for images and logos needs to be implemented.

Tasks

  • [ ] (1) Design and implement backend endpoints to allow read/write operations for custom branding
  • [ ] (2) Adapt the UI to allow the upload of images and icons.

We won't let the user select the name or folder of the file, just upload one, or reset to the original.

The tasks above might be elevated to issues, for the time being, this is what it's required:

  1. GET, PUT & DELETE operations to read, upload and reset custom imagery. No files are created or removed, only read and overwritten. See the parent issue for details. We need to be very careful with these endpoints in terms of security. The image must be validated in the backend (format and dimensions). Their names and paths must be decided beforehand, by the backend.

  2. Replace the text inputs by file pickers from the EUI framework. Validate the files in the frontend (format and dimensions). Send the files to the new endpoints. image

Depends on: #4443

AlexRuiz7 avatar Sep 01 '22 09:09 AlexRuiz7

Proposal

The previous settings to customize the subpath where the assets were exposed in the plugin platform server are no longer necessary.

Design specifications

The configuration of these settings will be done in the Settings/Configuration section of the UI.

These settings will use a file picker to drag or select the file. It should validate the supported extensions of the input file (this could change in the future of the implementation).

If the setting is configured, the UI will display a preview of the image and a button besides it to remove the image.

It is required to create new backend endpoints to manage the upload and removal of the assets.

Tasks

  • [x] Define where the assets are saved. <PLUGIN_PATH>/assets/custom/<type>. For the images, <type> is images
  • [x] Remove the settings related to the logo customizations from the plugin configuration file.
  • [x] Update the plugin configuration with these new values. This affects how the app reads the configuration (new models and validation need to be created).
  • [x] Implement access control to the assets (URL of the exposed static file or file system path)
  • [x] Implement the UI with new input components. File pickers will be used for the imagery. When custom images are set, the following UI components are added:
    • [x] Image preview
    • [x] Remove button
  • [x] Implement backend endpoints to manage the upload and removal of these assets
    • [x] Implement backend endpoint to upload custom imagery and branding texts.
    • [x] Implement backend endpoint to remove custom imagery and branding texts.
  • [x] Implement new logic to manage these settings from the UI.
  • [x] Provide support for the required file extensions (.png, .svg, .jpeg) (not final).
  • [x] Provide suggestions for image dimensions.
  • [x] Validate the uploaded file extensions
    • [x] in the frontend.
    • [x] in the backend.
  • [x] Validate the images do not exceed the maximum size. 1MB.
  • [x] Tests

Desvelao avatar Sep 05 '22 10:09 Desvelao

Details of the new plugin's settings

Due to the new design, the current logo customization will be removed, as file upload was not possible. Also, we want to support multiple file extensions to make it easier for the final user. As a consequence, the plugin will need to be aware of the file extension being used. In case of having several extensions for the same image, one, and only one of them must be used (priorities have to be defined yet). The UI must be aware of this selected setting in order to use the correct content type in the image preview.

An approach to this requirement would be to return this information in the same backend endpoint call that returns the plugin's settings (GET /utils/configuration). To do this, we'll need to compare:

  • the settings defined in the plugin's configuration file.
  • the custom assets stored in the expected path.

These changes will be implemented in the getConfiguration backend service and the mentioned route to get the plugin's configuration.

Desvelao avatar Sep 05 '22 10:09 Desvelao

Specifications of endpoints to manage the assets

Target path: <PLUGIN_PATH>/assets/custom/images/<custom-logo>

We need to study if it's possible to store the custom assets in a directory that is not affected by the pulgin's update (persistence). For example: <PLUGIN_PLATFORM_PATH>/data/wazuh/assets. This requires exposing this directory (research if this is possible).

File upload

  • Route: PUT /utils/configuration/files/<custom-logo>
  • Pre-conditions:
    • authenticated user (if the plugin platform security is enabled)
    • valid API token
    • administrator API role
  • Body:
    • file: raw image data
  • Actions:
    • Save the file in the target path, using the hard-coded filename and overwriting any existing custom image.

File removal

  • Route: DELETE /utils/configuration/files/<custom-logo>
  • Pre-conditions:
    • authenticated user (if the plugin platform security is enabled)
    • valid API token
    • administrator API role
  • Actions:
    • Overwrite the custom image with the official Wazuh imagery.

Desvelao avatar Sep 05 '22 10:09 Desvelao

UI design

The following things have been done:

  • A file picker input component has been added, linked to the new plugin's settings (custom imagery)
  • Add image preview, if present.
  • Add remove button and confirmation prompt, if custom images are set.

Screenshots

  • Addition of file pickers

image

  • UI preview when custom images are set

image

  • Hovering the remove icon

image

  • Confirmation to remove the custom image

image

Desvelao avatar Sep 07 '22 07:09 Desvelao

Changes in the specification

  • The settings related to the image customization should be kept in the plugin's configuration file.

Tasks

  • [x] Add back the settings in the configuration file, and adapt the current changes to allow these settings again.

Desvelao avatar Sep 07 '22 12:09 Desvelao

Latest changes:

  • Removed the composition of settings. Now all the settings are retrieved from the configuration file.
    • Adapted the getConfiguration backend service.
    • Adapted the upload and removal of custom files.
  • Added validation of the parameter's types for the new backend endpoints.
  • Added new properties to the setting's schema in order to do the following:
    • define the filename of the images (cannot be changed by the users for security reasons)
    • define how the image will be stored, and where (path)
    • define how the URL of the asset will be resolved (public assets' directory)
    • to manage how to store the file, define the filename to save in the file system and

Desvelao avatar Sep 07 '22 15:09 Desvelao

  • Refactorized the input components to be reusable.
  • Uncoupled the preview image and the update button components when custom imagery is used.

Desvelao avatar Sep 08 '22 15:09 Desvelao

  • UI preview when custom images are set

image

Question: can the remove button be removed?? The file picker already has an option to remove the file, if it works, then the remove button is redundant.

AlexRuiz7 avatar Sep 14 '22 10:09 AlexRuiz7

  • UI preview when custom images are set

image

Question: can the remove button be removed?? The file picker already has an option to remove the file, if it works, then the remove button is redundant.

The button to Remove the file from the file picker only appear if there is a selected file. If the setting is set, and the user goes to Settings/Configuration, the file picker has no selected file, it is empty.

Desvelao avatar Sep 15 '22 06:09 Desvelao

Changes

  • The inputs from the file pickers are now cleaned when the configuration has been saved.

There is an error displayed in the console when using the removeFiles method of the EuiFilePicker component.

Desvelao avatar Sep 19 '22 13:09 Desvelao

Limit the size of the uploaded file

We can limit the maximum size of the uploaded file by defining the options.body.maxBytes route property.

router.put(
    {
      path: '/utils/configuration/files/{key}',
      validate: validation,
      options: {
        body: {
          maxBytes: <MAXIMUM_BYTES_PAYLOAD_UPLOAD_CUSTOM_FILE>,
        },
      }
    },
    handler
  );

Information about the routes' options: https://github.com/elastic/kibana/blob/v7.10.2/src/core/server/http/router/route.ts#L81-L86

But the user can define a global value for using server.maxPayload (Kibana 7.10.2). Default: 1048576.

Do we want to set this value for the endpoint to upload the custom images? What value in bytes?

Desvelao avatar Sep 19 '22 13:09 Desvelao

New requirement

  • [x] Limit the maximum body size to upload files to 1 MB

Desvelao avatar Sep 21 '22 11:09 Desvelao

Changes

Frontend

  • Add size validation of the selected file of the file picker image

Backend

  • Add size validation of the request payload size. :exclamation: The endpoint receives more information than the file, so its value limits the total size. This difference does that the frontend validates successfully a file whose size is the same or near to the limit, and when saving the configuration, the backend throws a validation error.

Desvelao avatar Sep 23 '22 10:09 Desvelao

Changes

Frontend

  • Add size validation of the selected file of the file picker image

Backend

  • Add size validation of the request payload size. exclamation The endpoint receives more information than the file, so its value limits the total size. This difference does that the frontend validates successfully a file whose size is the same or near to the limit, and when saving the configuration, the backend throws a validation error.

Can the unit be megabytes, or at least kilobytes?

AlexRuiz7 avatar Sep 23 '22 11:09 AlexRuiz7

Changes

Frontend

  • Add size validation of the selected file of the file picker image

Backend

  • Add size validation of the request payload size. exclamation The endpoint receives more information than the file, so its value limits the total size. This difference does that the frontend validates successfully a file whose size is the same or near to the limit, and when saving the configuration, the backend throws a validation error.

Can the unit be megabytes, or at least kilobytes?

I added a service to format the value to a meaningful unit.

Screenshots image

Desvelao avatar Sep 26 '22 05:09 Desvelao

TR:

Screencast from 26-10-22 10:34:07.webm

Screencast from 26-10-22 10:49:12.webm

Detected Problems: I can't used an SVG file to PDF logo. Used File:

image (4)

Mayons95 avatar Oct 26 '22 15:10 Mayons95

't used an SVG file to PDF logo

The customization.logo.reports setting can not use an SVG image.

Desvelao avatar Oct 27 '22 06:10 Desvelao