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

Upload file for `customization.logo.*` settings

Open Desvelao opened this issue 2 years ago • 4 comments

Description

Changes

Add endpoints to manage the upload/deletion

  • Upload: PUT /utils/configuration/files/{key}
  • Deletion: DELETE /utils/configuration/files/{key}

Add plugin setting type: filepicker Add filepicker input form component Display the customized image in Settings/Configuration Add a button to remove the customized image

Closes #4434

Screenshots

  • Setting configuration using a file picker image
  • When there is a custom image set image
  • Hovering the remove icon image
  • Confirmation to remove the custom image image

Tests

Manual tests

Scenario: Select a valid file for each customization.logo.* setting in Settings/Configuration When the user drag-and-drops or selects a file Then the file picker only should accept the supported file extensions

Scenario: Upload the configuration for a customization.logo.* setting in Settings/Configuration When the user selects a valid file and click on the Save button Then the file should be saved in the expected path of the filesystem: WAZUH_PLUGIN_PATH/public/assets/custom/images whose filename is the setting key and the extension is the same of the uploaded file. And the image should be displayed depending on the setting customized. Currently: customization.logo.sidebar require to reload the browser tab. And the configuration should be modified to include the setting and its value is the path to the file should be exposed.

This scenario should be done with all the customization.logo.* settings.

Scenario: Delete the customization of each customization.logo.* in Settings/Configuration Given the setting is customized When the user clicks on the button to remove the file Then the file should be removed from the file system: WAZUH_PLUGIN_PATH/public/assets/custom/images. And the UI should display the custom image. Currently: customization.logo.sidebar require to reload the browser tab. And the configuration for the setting should be cleaned

This scenario should be done with all the customization.logo.* settings.

Scenario: Update the plugin configuration from Settings/Configuration modifying mutiple settings at the same time Given the users modifies some setting that is not a customization.logo.* and a of customization.logo.* setting When the user clicks on the button to save Then the file should be saved in the expected path of the filesystem: WAZUH_PLUGIN_PATH/public/assets/custom/images whose filename is the setting key and the extension is the same of the uploaded file. And the image should be displayed depending on the setting customized. Currently: customization.logo.sidebar require to reload the browser tab. And the configuration should be modified to include the setting and its value is the path to the file should be exposed. And the setting that is not a customization.logo.* setting should be saved in the configuration file

Scenario: Update the plugin configuration from Settings/Configuration modifying multiple settings at the same time with 2 or more customization.logo.* settings Given the users modify some setting that is not a customization.logo.* and 2 or more of customization.logo.* settings When the user clicks on the button to save Then the files should be saved in the expected path of the filesystem: WAZUH_PLUGIN_PATH/public/assets/custom/images whose filename is the setting key and the extension is the same of the uploaded file. And the images should be displayed depending on the setting customized. Currently: customization.logo.sidebar require to reload the browser tab. And the configuration should be modified to include the settings and its value is the path to the files that should be exposed. And the setting that is not a customization.logo.* setting should be saved in the configuration file

Desvelao avatar Sep 13 '22 09:09 Desvelao

Different aspect ratio example

image

asteriscos avatar Sep 14 '22 18:09 asteriscos

Pending

  • [x] Clear the file picker state when the file is uploaded

image

asteriscos avatar Sep 16 '22 18:09 asteriscos

Changes

  • If there are selected files in the file picker inputs, and saving the configuration, the file picker inputs will be cleaned.

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

Update

  • Update the development branch with the last changes of the base branch.

Desvelao avatar Sep 23 '22 08:09 Desvelao

Detecting the image's format from its metadata

Yesterday, in a sync meeting, we decide to get the file extension from the buffer instead of the current logic that send the file and the extension as another field.

@AlexRuiz7 commented on the possibility to check the headers of the file. He worked in a solution transforming the file buffer to hex string and reading the first four characters. The core of its solution looks like:

/**
 * Loads an image from the filesystem and returns it as a hex string
 * @param {String} filename image to load. Must exist in the assets/ directory.
 * @returns hex representation of the loaded image.
 */
function loadImageAsHex(filename) {
    const bitmap = fs.readFileSync(`./assets/${filename}`);
    return bitmap.toString('hex');
}

/**
 * Calculates the image format by reading the first 4 bytes of the image (header)
 * Supported types: jpeg, jpg, png, svg
 * Additionally, this function allows checking gif images.
 * @param {String} hexImageData hex representation of the image 
 * @returns 
 */
function getImageFormat(hexImageData) {
    const imageFormat = hexImageData.substring(0, 4);
    switch (imageFormat) {
        case '8950':
            return 'png';
        case '4749':
            return 'gif';
        case 'ffd8':
            return 'jpg';   // Also jpeg
        case '3c3f':
            return 'svg';
        default:
            return 'unknown';
    }
}

I have been working around the initial idea. Comparing the bytes array, I got a functional solution. get-extension-file-from-buffer-using-array-bytes.patch.txt

I think the solution of @AlexRuiz7 is more simple, and we could implement it.

Desvelao avatar Oct 06 '22 08:10 Desvelao

Update

  • Changed the file extension detection mechanism when uploading the file. Now, the extension is read from the file buffer. The solution is based on https://github.com/wazuh/wazuh-kibana-app/pull/4504#issuecomment-1269544233.
    • Create a service to get the file extension
    • Add some tests for the service
    • Remove the previous logic and adapt to use the service

Desvelao avatar Oct 06 '22 09:10 Desvelao

Update

  • Update the development branch with the base branch

Desvelao avatar Oct 06 '22 09:10 Desvelao

Would you have to change to the branch you are merging to?

yenienserrano avatar Oct 26 '22 09:10 yenienserrano

Would you have to change to the branch you are merging to?

Changed.

Desvelao avatar Oct 26 '22 10:10 Desvelao

Update

  • Fixed a problem with an unexpected attribute for the input of type number.
  • Fixed a problem when removing the configuration for customization.logo.reports that displayed the original logo when should not.

Desvelao avatar Oct 26 '22 11:10 Desvelao

Update

  • Change the layout of the filepicker input and the logo with the button to remove the configuration.

Screenshots :computer: Desktop image image


:iphone: Mobile image image

Desvelao avatar Oct 26 '22 15:10 Desvelao

TR Comments: We performed a script with @Desvelao and @asteriscos to test the API file upload, I left the script here, to use it, it's necessary to update the cookie value.

script.tar.gz

Screencast from 27-10-22 10:25:46.webm

Screencast from 27-10-22 10:27:49.webm

Screencast from 27-10-22 10:29:45.webm

Screencast from 27-10-22 10:30:48.webm

Mayons95 avatar Oct 27 '22 13:10 Mayons95

Some problems found by @AlexRuiz7

Environment: Kibana 7.10.2 development mode.

The endpoint to remove the configuration for the customization.logo.* setting doesn't work.

Endpoint: DELETE /utils/configuration/files/{key}

We were researching and saw that could be caused by the development proxy (not using the --no-base-path when starting the server) and accessing using the 5601 port instead of the mentioned port 5603 in the logs of the platform. We do not know the reason for the problem.

Others requests with the same HTTP verb (DELETE) fail too. image

Some custom logos are not visible when using SVG images.

This problem happens in:

  • custom image preview in Settings/Configuration
  • plugin menu

This is caused because the SVG image has not defined the height and width properties. Read more here: https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/SVG_Image_Tag image

If these properties are added, the problem disappears. image image

@AlexRuiz7 reported that by using the same SVG for other settings as customization.logo.healthcheck and customization.logo.sidebar, the images are displayed correctly. This means that some styles could be affecting how the browser should render the image.

Research - Custom image preview in Settings/Configuration

I found that if the width: auto CSS property is removed from the element style, the image is displayed correctly. This property is set by the EuiImage component when the size property is defined as a number https://github.com/elastic/eui/blob/v29.3.2/src/components/image/image.tsx#L140.

EDIT: I pushed a commit to solve this problem.

Research - Plugin menu

EDIT: I pushed a commit to solve this problem.

Desvelao avatar Oct 28 '22 08:10 Desvelao

In a meeting with @asteriscos , we saw a problem related to the browser cache and the customization.logo.* settings used in the frontend UI.

How to replicate:

  1. Upload an image with some extension (jpg, png, svg)
  2. Upload another image with the same extension as step 1. The UI display doesn't change and displays the image of step one. Cleaning the browser cache solves the problem.

We want to research a solution that does not implicate cleaning the browser cache and minimizes the users.

Desvelao avatar Oct 28 '22 09:10 Desvelao

In a meeting with @asteriscos , we saw a problem related to the browser cache and the customization.logo.* settings used in the frontend UI.

How to replicate:

  1. Upload an image with some extension (jpg, png, svg)
  2. Upload another image with the same extension as step 1. The UI display doesn't change and displays the image of step one. Cleaning the browser cache solves the problem.

We want to research a solution that does not implicate cleaning the browser cache and minimizes the users.

Solved in https://github.com/wazuh/wazuh-kibana-app/pull/4504/commits/ccd57ca7c2d00ec43eb199f452ddf5a1b42b5188.

Desvelao avatar Oct 28 '22 09:10 Desvelao

In a meeting with @asteriscos , we saw a problem related to the browser cache and the customization.logo.* settings used in the frontend UI. How to replicate:

  1. Upload an image with some extension (jpg, png, svg)
  2. Upload another image with the same extension as step 1. The UI display doesn't change and displays the image of step one. Cleaning the browser cache solves the problem.

We want to research a solution that does not implicate cleaning the browser cache and minimizes the users.

Solved in ccd57ca.

Now when an image is uploaded, the path saved in the configuration includes a version number to handle browser cache issues. Eg. customization.logo.app: "custom/images/customization.logo.app.png?v=1666948554416"

asteriscos avatar Oct 28 '22 09:10 asteriscos

Code coverage (Jest) % values
Statements 8.1% ( 2966 / 36623 )
Branches 3.71% ( 1045 / 28192 )
Functions 7.01% ( 636 / 9073 )
Lines 8.15% ( 2858 / 35054 )

github-actions[bot] avatar Oct 28 '22 09:10 github-actions[bot]

The backport to 4.4-7.16 failed:

The process '/usr/bin/git' failed with exit code 1

To backport manually, run these commands in your terminal:

# Fetch latest updates from GitHub
git fetch
# Create a new working tree
git worktree add .worktrees/backport-4.4-7.16 4.4-7.16
# Navigate to the new working tree
cd .worktrees/backport-4.4-7.16
# Create a new branch
git switch --create backport-4504-to-4.4-7.16
# Cherry-pick the merged commit of this pull request and resolve the conflicts
git cherry-pick -x --mainline 1 bc51482632ace29a9c174a31cd34ec0c12a88d47
# Push it to GitHub
git push --set-upstream origin backport-4504-to-4.4-7.16
# Go back to the original working tree
cd ../..
# Delete the working tree
git worktree remove .worktrees/backport-4.4-7.16

Then, create a pull request where the base branch is 4.4-7.16 and the compare/head branch is backport-4504-to-4.4-7.16.

github-actions[bot] avatar Oct 28 '22 10:10 github-actions[bot]

The backport to 4.4-2.3-wzd failed:

The process '/usr/bin/git' failed with exit code 1

To backport manually, run these commands in your terminal:

# Fetch latest updates from GitHub
git fetch
# Create a new working tree
git worktree add .worktrees/backport-4.4-2.3-wzd 4.4-2.3-wzd
# Navigate to the new working tree
cd .worktrees/backport-4.4-2.3-wzd
# Create a new branch
git switch --create backport-4504-to-4.4-2.3-wzd
# Cherry-pick the merged commit of this pull request and resolve the conflicts
git cherry-pick -x --mainline 1 bc51482632ace29a9c174a31cd34ec0c12a88d47
# Push it to GitHub
git push --set-upstream origin backport-4504-to-4.4-2.3-wzd
# Go back to the original working tree
cd ../..
# Delete the working tree
git worktree remove .worktrees/backport-4.4-2.3-wzd

Then, create a pull request where the base branch is 4.4-2.3-wzd and the compare/head branch is backport-4504-to-4.4-2.3-wzd.

github-actions[bot] avatar Oct 28 '22 10:10 github-actions[bot]