Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid force check updates when user logins #6375

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions plugins/main/public/components/settings/api/api-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,14 @@ export const ApiTable = compose(
};
}

async getApisAvailableUpdates(forceUpdate = false) {
async getApisAvailableUpdates(queryApi = false, forceQuery = false) {
try {
this.setState({ refreshingAvailableUpdates: true });
const availableUpdates =
await getWazuhCheckUpdatesPlugin().getAvailableUpdates(forceUpdate);
await getWazuhCheckUpdatesPlugin().getAvailableUpdates(
queryApi,
forceQuery,
);
this.setState({ availableUpdates });
} catch (error) {
const options = {
Expand Down Expand Up @@ -548,12 +551,14 @@ export const ApiTable = compose(
<EuiFlexItem grow={false}>
<EuiButtonEmpty
iconType='refresh'
onClick={async () => await this.getApisAvailableUpdates(true)}
onClick={async () =>
await this.getApisAvailableUpdates(true, true)
}
>
<span>
Check updates{' '}
<EuiToolTip
title='Last check'
title='Last dashboard check'
content={
this.state.availableUpdates?.last_check_date
? getWazuhCorePlugin().utils.formatUIDate(
Expand Down
5 changes: 4 additions & 1 deletion plugins/wazuh-check-updates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ Every time a page is loaded, the UpdatesNotification component is rendered. The
1. **User Preferences:** It retrieves information from the saved object containing user preferences to determine if the user has chosen to display more notifications about new updates and to obtain the latest updates that the user dismissed in a notification.

2. **Available Updates:** It retrieves the available updates for each available API. To determine where to retrieve the information, it first checks the session storage for the key `checkUpdates`. If the value is `executed`, it then searches for available updates in a saved object; otherwise, it queries the Wazuh API and makes a request for each available API, finally saving the information in the saved object and setting the session storage `checkUpdates` to `executed`.
The endpoint has two parameters:
`query_api`: Determines whether the Check Updates plugin retrieves data from the Wazuh API or from a saved object.
`force_query`: When `query_api` is set to true, it determines whether the Wazuh API internally obtains the data or fetches it from the CTI Service.

If the user had not chosen not to receive notifications of new updates and if the new updates are different from the last ones dismissed, then the component renders a bottom bar to notify that there are new updates.

Expand All @@ -28,7 +31,7 @@ The plugin provides a function for fetching the available updates for each API.
2. The main Wazuh plugin is loaded and renders the UpdatesNotification component from the Check Updates plugin.
3. The `UpdatesNotification` component checks the user's preferences (stored in a saved object) to determine if the user has dismissed notifications about new updates. If the user has dismissed them, the component returns nothing; otherwise, it proceeds to the next steps.
4. The UpdatesNotification component checks the `checkUpdates` value in the browser's session storage to determine if a query about available updates from the Wazuh Server API has already been executed. Since the user has just logged in, this value will not exist in the session storage.
5. The component makes a request to the Check Updates plugin API with the `checkAvailableUpdates` parameter set to true. This indicates the plugin's API to check for updates on all configured APIs. The `checkUpdates` value in the session storage is updated to `true`.
5. The component makes a request to the Check Updates plugin API with the `query_api` parameter set to true and `force_query` set to false. The `checkUpdates` value in the session storage is updated to `true`.
6. The updates are stored in a saved object for future reference.
7. It's possible that the user has dismissed specific updates. In such cases, the dismissed updates are compared with the updates retrieved from the API. If they match, the component returns nothing; otherwise, it proceeds to the next steps.
8. The component displays a bottom bar to notify the user of the availability of new updates.
Expand Down
11 changes: 7 additions & 4 deletions plugins/wazuh-check-updates/public/services/available-updates.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { useState, useEffect } from 'react';
import { ApiAvailableUpdates, AvailableUpdates } from '../../common/types';
import { AvailableUpdates } from '../../common/types';
import { routes } from '../../common/constants';
import { getCore } from '../plugin-services';

export const getAvailableUpdates = async (forceUpdate = false): Promise<AvailableUpdates> => {
export const getAvailableUpdates = async (
queryApi = false,
forceQuery = false,
): Promise<AvailableUpdates> => {
const checkUpdates = sessionStorage.getItem('checkUpdates');
const alreadyCheckUpdates = checkUpdates === 'executed';

const availableUpdates = await getCore().http.get(routes.checkUpdates, {
query: {
checkAvailableUpdates: forceUpdate || !alreadyCheckUpdates,
query_api: queryApi || !alreadyCheckUpdates,
force_query: forceQuery,
},
});

Expand Down
5 changes: 4 additions & 1 deletion plugins/wazuh-check-updates/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ export interface WazuhCheckUpdatesPluginSetup {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface WazuhCheckUpdatesPluginStart {
UpdatesNotification: () => JSX.Element | null;
getAvailableUpdates: (forceUpdate: boolean) => Promise<AvailableUpdates>;
getAvailableUpdates: (
queryApi: boolean,
forceQuery: boolean,
) => Promise<AvailableUpdates>;
DismissNotificationCheck: () => JSX.Element | null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe(`[endpoint] GET ${routes.checkUpdates}`, () => {

mockedGetUpdates.mockImplementation(() => mockResponse);
const response = await supertest(innerServer.listener)
.get(`${routes.checkUpdates}?checkAvailableUpdates=true`)
.get(`${routes.checkUpdates}?query_api=true`)
.send(mockResponse)
.expect(200);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ export const getUpdatesRoute = (router: IRouter) => {
path: routes.checkUpdates,
validate: {
query: schema.object({
checkAvailableUpdates: schema.maybe(schema.string()),
query_api: schema.maybe(schema.string()),
force_query: schema.maybe(schema.string()),
}),
},
},
async (context, request, response) => {
try {
const updates = await getUpdates(
request.query?.checkAvailableUpdates === 'true',
request.query?.query_api === 'true',
request.query?.force_query === 'true',
);
return response.ok({
body: updates,
Expand Down
22 changes: 14 additions & 8 deletions plugins/wazuh-check-updates/server/services/updates/get-updates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ import { SAVED_OBJECT_UPDATES } from '../../../common/constants';
import { getSavedObject, setSavedObject } from '../saved-object';
import { getWazuhCore } from '../../plugin-services';

export const getUpdates = async (checkAvailableUpdates?: boolean): Promise<AvailableUpdates> => {
export const getUpdates = async (
queryApi = false,
forceQuery = false,
): Promise<AvailableUpdates> => {
try {
if (!checkAvailableUpdates) {
const availableUpdates = (await getSavedObject(SAVED_OBJECT_UPDATES)) as AvailableUpdates;
if (!queryApi) {
const availableUpdates = (await getSavedObject(
SAVED_OBJECT_UPDATES,
)) as AvailableUpdates;

return availableUpdates;
}
Expand All @@ -21,13 +26,14 @@ export const getUpdates = async (checkAvailableUpdates?: boolean): Promise<Avail
} = getWazuhCore();
const wazuhHostsController = new WazuhHostsCtrl();

const hosts: { id: string }[] = await wazuhHostsController.getHostsEntries();
const hosts: { id: string }[] =
await wazuhHostsController.getHostsEntries();

const apisAvailableUpdates = await Promise.all(
hosts?.map(async (api) => {
hosts?.map(async api => {
const data = {};
const method = 'GET';
const path = '/manager/version/check?force_query=true';
const path = `/manager/version/check?force_query=${forceQuery}`;
const options = {
apiHostID: api.id,
forceRefresh: true,
Expand All @@ -37,7 +43,7 @@ export const getUpdates = async (checkAvailableUpdates?: boolean): Promise<Avail
method,
path,
data,
options
options,
);

const update = response.data.data as ResponseApiAvailableUpdates;
Expand Down Expand Up @@ -89,7 +95,7 @@ export const getUpdates = async (checkAvailableUpdates?: boolean): Promise<Avail
error,
};
}
})
}),
);

const savedObject = {
Expand Down
Loading